diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt index bd9c376..dd8bbc8 100644 --- a/platform/CMakeLists.txt +++ b/platform/CMakeLists.txt @@ -60,3 +60,24 @@ target_link_libraries(test_tfe_rpc pthread dl MESA_field_stat) install(TARGETS test_tfe_rpc RUNTIME DESTINATION ./) + + +### test_chello_parse +add_executable(test_chello_parse test/test_chello_parse.cpp src/ssl_utils.cc) + +target_include_directories(test_chello_parse PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include/internal) + +target_link_libraries(test_chello_parse common) +target_link_libraries(test_chello_parse pthread dl + openssl-ssl-static + openssl-crypto-static + pthread libevent-static + libevent-static-openssl + libevent-static-pthreads + MESA_handle_logger + MESA_prof_load + MESA_htable wiredcfg + cjson + MESA_field_stat) + +install(TARGETS test_chello_parse RUNTIME DESTINATION ./) diff --git a/platform/include/internal/ssl_utils.h b/platform/include/internal/ssl_utils.h index c1e50ae..4bd1377 100644 --- a/platform/include/internal/ssl_utils.h +++ b/platform/include/internal/ssl_utils.h @@ -178,4 +178,31 @@ int ssl_tls_clienthello_parse(const unsigned char *, ssize_t, int, int ssl_dnsname_match(const char *, size_t, const char *, size_t); char * ssl_wildcardify(const char *); + +enum parse_chello_result +{ + PARSE_CHELLO_INVALID_FORMAT = 0, + PARSE_CHELLO_NOT_ENOUGH_BUFF, + PARSE_CHELLO_SUCCESS +}; + +struct ssl_version +{ + uint8_t major; + uint8_t minor; +}; + +struct ssl_chello +{ + struct ssl_version record_layer_version; + struct ssl_version chello_version; + char* sni; + char* alpn; + char* cipher_suites; + char* cipher_suites_tls13; +}; +struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len, enum parse_chello_result* result); + +void ssl_chello_free(struct ssl_chello* chello); + #endif /* !SSL_H */ diff --git a/platform/src/ssl_utils.cc b/platform/src/ssl_utils.cc index 5549eb0..17bf877 100644 --- a/platform/src/ssl_utils.cc +++ b/platform/src/ssl_utils.cc @@ -1648,7 +1648,7 @@ int ssl_is_ocspreq(const unsigned char * buf, size_t sz) struct cipher_suite { int value; - char* name; + const char* name; }; struct cipher_suite cipher_suite_list[] = @@ -1782,30 +1782,6 @@ struct cipher_suite cipher_suite_list_tls13[] = {0x1305, "TLS_AES_128_CCM_8_SHA256"} }; -enum parse_chello_result -{ - PARSE_CHELLO_INVALID_FORMAT = 0, - PARSE_CHELLO_NOT_ENOUGH_BUFF, - PARSE_CHELLO_SUCCESS -}; - - -struct ssl_version -{ - int major; - int minor; -}; - -struct ssl_chello -{ - struct ssl_version record_layer_version; - struct ssl_version chello_version; - char* sni; - char* alpn; - char* cipher_suites; - char* cipher_suites_tls13; -}; - void ssl_chello_free(struct ssl_chello* chello) { @@ -1820,21 +1796,141 @@ void ssl_chello_free(struct ssl_chello* chello) free(chello); } -struct chello* ssl_chello_parse(const char* buff, size_t buff_len, enum parse_chello_result* result) +static char* parse_alpn_extension(const unsigned char* buff, size_t buff_len, enum parse_chello_result* result) +{ + size_t pos = 0; + size_t len = ((size_t)buff[pos] << 8) + (size_t)buff[pos + 1]; + if(2 + len != buff_len) + { + *result = PARSE_CHELLO_INVALID_FORMAT; + return NULL; + } + char* alpn = (char*)malloc(len + 1); + strncpy(alpn, (const char*)buff + 2, len); + alpn[len] = '\0'; + *result = PARSE_CHELLO_SUCCESS; + return alpn; +} + +static char* parse_server_name_extension(const unsigned char* buff, size_t buff_len, enum parse_chello_result* result) +{ + size_t pos = 2; /* skip server name list length */ + size_t len; + char* sni = NULL; + while (pos + 3 < buff_len) + { + len = ((size_t)buff[pos + 1] << 8) + (size_t)buff[pos + 2]; + if (pos + 3 + len > buff_len) + { + *result = PARSE_CHELLO_INVALID_FORMAT; + return NULL; + } + switch (buff[pos]) + { + case 0x00: /* host_name */ + sni = (char*)malloc(len + 1); + strncpy(sni, (const char*)buff + pos + 3, len); + sni[len] = '\0'; + *result = PARSE_CHELLO_SUCCESS; + } + pos += 3 + len; + } + if (pos != buff_len) + { + *result = PARSE_CHELLO_INVALID_FORMAT; + } + return sni; +} + +static enum parse_chello_result parse_extensions(const unsigned char* buff, size_t buff_len, struct ssl_chello* chello) { + size_t pos = 0; + /* Parse each 4 bytes for the extension header */ + while (pos + 4 <= buff_len) + { + size_t len = ((size_t)buff[pos + 2] << 8) + (size_t)buff[pos + 3]; + /* Check if it's a server name extension */ + if (buff[pos] == 0x00 && buff[pos + 1] == 0x00) + { + if (pos + 4 + len > buff_len) + { + return PARSE_CHELLO_INVALID_FORMAT; + } + enum parse_chello_result result = PARSE_CHELLO_SUCCESS; + chello->sni = parse_server_name_extension(buff + pos + 4, len, &result); + if(result != PARSE_CHELLO_SUCCESS) + { + return result; + } + } + /* Check if it's a alpn extension */ + if (buff[pos] == 0x00 && buff[pos + 1] == 0x10) + { + if (pos + 4 + len > buff_len) + { + return PARSE_CHELLO_INVALID_FORMAT; + } + enum parse_chello_result result = PARSE_CHELLO_SUCCESS; + chello->alpn = parse_alpn_extension(buff + pos + 4, len, &result); + if(result != PARSE_CHELLO_SUCCESS) + { + return result; + } + } + pos += (4 + len); + } + /* Check we ended where we expected to */ + if (pos != buff_len) + { + return PARSE_CHELLO_INVALID_FORMAT; + } + return PARSE_CHELLO_SUCCESS; +} + +static char* parse_cipher_suites(struct cipher_suite* _cipher_suite_list, int n, const unsigned char* buff, size_t buff_len, enum parse_chello_result* result) +{ + char* cipher_suites_str = (char* )malloc(TFE_STRING_MAX); + cipher_suites_str[0] = '\0'; + size_t pos = 0; + while(pos < buff_len) + { + int i = 0; + for(i = 0;i < n; i++) + { + int val = (buff[pos] << 8) + buff[pos + 1]; + if(_cipher_suite_list[i].value == val) + { + strncat(cipher_suites_str, _cipher_suite_list[i].name, TFE_STRING_MAX); + strncat(cipher_suites_str, ":", TFE_STRING_MAX); + } + } + pos += 2; + } + int len = strnlen(cipher_suites_str, TFE_STRING_MAX); + cipher_suites_str[len-1] = '\0'; + if(pos != buff_len) + { + *result = PARSE_CHELLO_INVALID_FORMAT; + return NULL; + } + *result = PARSE_CHELLO_SUCCESS; + return cipher_suites_str; +} + +struct ssl_chello* ssl_chello_parse(const unsigned char* buff, size_t buff_len, enum parse_chello_result* result) { if(buff == NULL) { - result = PARSE_CHELLO_INVALID_FORMAT; + *result = PARSE_CHELLO_INVALID_FORMAT; return NULL; } if(buff_len < 1) { - result = PARSE_CHELLO_NOT_ENOUGH_BUFF; + *result = PARSE_CHELLO_NOT_ENOUGH_BUFF; return NULL; } if(buff[0] != 0x80 && buff[0] != 0x16) { - result = PARSE_CHELLO_INVALID_FORMAT; + *result = PARSE_CHELLO_INVALID_FORMAT; return NULL; } /* SSL 2.0 compatible Client Hello @@ -1844,7 +1940,7 @@ struct chello* ssl_chello_parse(const char* buff, size_t buff_len, enum parse_ch */ if(buff[0] == 0x80) { - struct chello* _chello = (struct chello*)ALLOC(struct chello, 1); + struct ssl_chello* _chello = (struct ssl_chello*)ALLOC(struct ssl_chello, 1); _chello->record_layer_version.major = 0x02; if(buff_len < 2) { @@ -1894,7 +1990,7 @@ struct chello* ssl_chello_parse(const char* buff, size_t buff_len, enum parse_ch *result = PARSE_CHELLO_INVALID_FORMAT; return NULL; } - struct chello* _chello = (struct chello*)ALLOC(struct chello, 1); + struct ssl_chello* _chello = (struct ssl_chello*)ALLOC(struct ssl_chello, 1); _chello->record_layer_version.major = buff[1]; _chello->record_layer_version.minor = buff[2]; _chello->chello_version.major = -1; @@ -1904,7 +2000,7 @@ struct chello* ssl_chello_parse(const char* buff, size_t buff_len, enum parse_ch _chello->cipher_suites = NULL; _chello->cipher_suites_tls13 = NULL; /* TLS record length */ - size_t len = ((size_t)buf[3] << 8) + (size_t)buf[4] + 5; + size_t len = ((size_t)buff[3] << 8) + (size_t)buff[4] + 5; if (buff_len < len) { *result = PARSE_CHELLO_NOT_ENOUGH_BUFF; @@ -1959,7 +2055,7 @@ struct chello* ssl_chello_parse(const char* buff, size_t buff_len, enum parse_ch return _chello; } n = sizeof(cipher_suite_list_tls13) / sizeof(struct cipher_suite); - _chello->cipher_suites_tls13 = parse_cipher_suites_tls13(cipher_suite_list_tls13, n, buff + pos, len, result); + _chello->cipher_suites_tls13 = parse_cipher_suites(cipher_suite_list_tls13, n, buff + pos, len, result); if(*result != PARSE_CHELLO_SUCCESS) { return _chello; @@ -2005,124 +2101,3 @@ struct chello* ssl_chello_parse(const char* buff, size_t buff_len, enum parse_ch return _chello; } } - -static enum parse_chello_result parse_extensions(const char* buff, size_t buff_len, struct chello* chello) { - size_t pos = 0; - /* Parse each 4 bytes for the extension header */ - while (pos + 4 <= buff_len) - { - size_t len = ((size_t)buff[pos + 2] << 8) + (size_t)buff[pos + 3]; - /* Check if it's a server name extension */ - if (buff[pos] == 0x00 && buff[pos + 1] == 0x00) - { - if (pos + 4 + len > buff_len) - { - return PARSE_CHELLO_INVALID_FORMAT; - } - pos + = 4; - enum parse_chello_result result = PARSE_CHELLO_SUCCESS; - chello->sni = parse_server_name_extension(data + pos, len, &result); - if(result != PARSE_CHELLO_SUCCESS) - { - return result; - } - } - /* Check if it's a alpn extension */ - if (buff[pos] == 0x00 && buff[pos + 1] == 0x10) - { - if (pos + 4 + len > buff_len) - { - return PARSE_CHELLO_INVALID_FORMAT; - } - pos + = 4; - enum parse_chello_result result = PARSE_CHELLO_SUCCESS; - chello->alpn = parse_alpn_extension(data + pos, len, &result); - if(result != PARSE_CHELLO_SUCCESS) - { - return result; - } - } - pos += len; - } - /* Check we ended where we expected to */ - if (pos != data_len) - { - return PARSE_CHELLO_INVALID_FORMAT; - } - return PARSE_CHELLO_SUCCESS; -} - -static const char* parse_cipher_suites(struct cipher_suite* _cipher_suite_list, int n, const char* buff, size_t buff_len, enum parse_chello_result* result) -{ - char* cipher_suites_str = malloc(TFE_STRING_MAX); - cipher_suites_str[0] = "\0"; - size_t pos = 0; - while(pos < buff_len) - { - int i = 0; - for(i = 0;i < n; i++) - { - int val = buff[pos] << 8 + buff[pos + 1]; - if(_cipher_suite_list[i].value == val) - { - strncat(cipher_suites_str, _cipher_suite_list[i].name, TFE_STRING_MAX); - } - } - pos += 2; - } - if(pos != buff_len) - { - *result = PARSE_CHELLO_INVALID_FORMAT; - return NULL; - } - *result = PARSE_CHELLO_SUCCESS; - return cipher_suites_str; -} - - -static const char* parse_alpn_extension(const char* buff, size_t buff_len, enum parse_chello_result* result) -{ - size_t len = ((size_t)buff[pos] << 8) + (size_t)buff[pos + 1]; - if(2 + len != buff_len) - { - *result = PARSE_CHELLO_INVALID_FORMAT; - return NULL; - } - char* alpn = malloc(len + 1); - strncpy(alpn, buff + 2, len); - alpn[len] = '\0'; - *result = PARSE_CHELLO_SUCCESS; - return alpn; -} - -static const char* parse_server_name_extension(const char* buff, size_t buff_len, enum parse_chello_result* result) -{ - size_t pos = 2; /* skip server name list length */ - size_t len; - const char* sni = NULL; - while (pos + 3 < buff_len) - { - len = ((size_t)buff[pos + 1] << 8) + (size_t)buff[pos + 2]; - if (pos + 3 + len > buff_len) - { - *result = PARSE_CHELLO_INVALID_FORMAT; - return NULL; - } - switch (buff[pos]) - { - case 0x00: /* host_name */ - sni = malloc(len + 1); - strncpy(sni, (const char *)(buff + pos + 3), len); - sni[len] = '\0'; - *result = PARSE_CHELLO_SUCCESS; - default: - sni = NULL; - } - pos += 3 + len; - } - if (pos != buff_len) - { - *result = PARSE_CHELLO_INVALID_FORMAT; - } - return sni; -} diff --git a/platform/test/test_chello_parse.cpp b/platform/test/test_chello_parse.cpp new file mode 100644 index 0000000..ab793a6 --- /dev/null +++ b/platform/test/test_chello_parse.cpp @@ -0,0 +1,154 @@ + +#include "ssl_utils.h" +#include "tfe_utils.h" +#include +#include +#include + +char* parse_alpn(const char* alpn) +{ + int size = strlen(alpn); + char* result = (char*)malloc(100); + result[0] = '\0'; + int i = 0; + for(i = 0;i < size; ) + { + int size1 = alpn[i]; + strncat(result, alpn + i + 1, size1); + strncat(result, ", ", 2); + i += (1 + size1); + } + int size2 = strlen(result); + result[size2] = '\0'; + return result; +} +int main() +{ + + //ssl2.0 + unsigned char buff[] = + { + 0x80, 0x77, 0x01, 0x03, 0x01, 0x00, 0x4e, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x38, 0x00, 0x00, 0x35, + 0x00, 0x00, 0x16, 0x00, 0x00, 0x13, 0x00, 0x00, 0x0a, 0x07, + 0x00, 0xc0, 0x00, 0x00, 0x33, 0x00, 0x00, 0x32, 0x00, 0x00, + 0x2f, 0x03, 0x00, 0x80, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, + 0x01, 0x00, 0x80, 0x00, 0x00, 0x15, 0x00, 0x00, 0x12, 0x00, + 0x00, 0x09, 0x06, 0x00, 0x40, 0x00, 0x00, 0x14, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x04, 0x00, 0x80, + 0x00, 0x00, 0x03, 0x02, 0x00, 0x80, 0x00, 0x00, 0xff, 0xe2, + 0xd8, 0x90, 0x3f, 0xbd, 0x26, 0x76, 0xb2, 0xf3, 0x8b, 0x1b, + 0x36, 0xed, 0x29, 0x04, 0x8d, 0x72, 0x1a, 0xe7, 0xc4, 0xd5, + 0xbc, 0x56, 0xb1, 0x63, 0x8e, 0x8d, 0x9e, 0x08, 0x74, 0xb9, + 0x69 + }; + size_t buff_len = sizeof(buff) / sizeof(char); + enum parse_chello_result result; + struct ssl_chello* chello = ssl_chello_parse(buff, buff_len, &result); + printf("-----------------------------ssl2.0 only parse version --------------------------------\n"); + printf("record layer version is %d, %d\n", chello->record_layer_version.major, chello->record_layer_version.minor); + printf("\n\n"); + ssl_chello_free(chello); + chello = NULL; + + //ssl3.0, no extensions + unsigned char buff1[] = + { + 0x16, 0x03, 0x00, 0x00, 0x51, 0x01, 0x00, 0x00, 0x4d, 0x03, + 0x00, 0x50, 0x42, 0xb2, 0x29, 0x1f, 0xcf, 0x52, 0xa0, 0x94, + 0x87, 0x05, 0xe7, 0x0b, 0x63, 0x08, 0x12, 0xa2, 0x6c, 0x59, + 0xf7, 0xf5, 0x72, 0x2b, 0x57, 0x14, 0xa7, 0x07, 0x95, 0xcb, + 0xce, 0xe5, 0xe4, 0x00, 0x00, 0x26, 0x00, 0x04, 0x00, 0x05, + 0x00, 0x2f, 0x00, 0x33, 0x00, 0x32, 0x00, 0x0a, 0xfe, 0xff, + 0x00, 0x16, 0x00, 0x13, 0x00, 0x66, 0x00, 0x09, 0xfe, 0xfe, + 0x00, 0x15, 0x00, 0x12, 0x00, 0x03, 0x00, 0x08, 0x00, 0x06, + 0x00, 0x14, 0x00, 0x11, 0x01, 0x00 + }; + size_t buff1_len = sizeof(buff1) / sizeof(char); + enum parse_chello_result result1; + struct ssl_chello* chello1 = ssl_chello_parse(buff1, buff1_len, &result1); + printf("--------------------------------ssl3.0, no extensions --------------------------------\n"); + printf("record layer version is %d, %d\n", chello1->record_layer_version.major, chello1->record_layer_version.minor); + printf("client hello version: %d, %d\n", chello1->chello_version.major, chello1->chello_version.minor); + printf("cipher suites is %s\n", chello1->cipher_suites); + if(chello1->cipher_suites_tls13) + { + printf("cipher suites for tls1.3 is %s\n", chello1->cipher_suites_tls13); + } + printf("\n\n"); + ssl_chello_free(chello1); + chello1 = NULL; + + //tls1.2 + unsigned char buff2[] = + { + 0x16, 0x03, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0xfc, 0x03, + 0x03, 0x30, 0x6d, 0x1d, 0xd5, 0x0d, 0xa6, 0x1e, 0x0b, 0xe6, + 0xf7, 0xf0, 0xd3, 0xfa, 0x14, 0xdc, 0x80, 0x24, 0xe5, 0x34, + 0x2d, 0x9c, 0x68, 0x6b, 0x0a, 0x40, 0x59, 0xc6, 0x2c, 0xbb, + 0xf1, 0x04, 0xee, 0x20, 0xc4, 0x33, 0x03, 0x91, 0xa9, 0x0d, + 0xfa, 0xae, 0x93, 0x9b, 0xbe, 0x22, 0x7c, 0x99, 0x5f, 0xaf, + 0xdc, 0xe1, 0x14, 0xab, 0xbc, 0x57, 0x1f, 0x7f, 0xe0, 0x5c, + 0x59, 0xe3, 0x8b, 0xaa, 0x70, 0xf8, 0x00, 0x22, 0x5a, 0x5a, + 0x13, 0x01, 0x13, 0x02, 0x13, 0x03, 0xc0, 0x2b, 0xc0, 0x2f, + 0xc0, 0x2c, 0xc0, 0x30, 0xcc, 0xa9, 0xcc, 0xa8, 0xc0, 0x13, + 0xc0, 0x14, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f, 0x00, 0x35, + 0x00, 0x0a, 0x01, 0x00, 0x01, 0x91, 0xea, 0xea, 0x00, 0x00, + 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, + 0x10, 0x00, 0x00, 0x0d, 0x77, 0x77, 0x77, 0x2e, 0x62, 0x61, + 0x69, 0x64, 0x75, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x17, 0x00, + 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x14, 0x00, + 0x12, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08, + 0x05, 0x05, 0x01, 0x08, 0x06, 0x06, 0x01, 0x02, 0x01, 0x00, + 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x0c, 0x02, 0x68, + 0x32, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, + 0x75, 0x50, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, + 0x00, 0x33, 0x00, 0x2b, 0x00, 0x29, 0xea, 0xea, 0x00, 0x01, + 0x00, 0x00, 0x1d, 0x00, 0x20, 0x1b, 0xae, 0xc9, 0x4f, 0x17, + 0x30, 0xf2, 0xec, 0x4c, 0xc1, 0xdb, 0xf7, 0xe4, 0x72, 0xad, + 0x22, 0xa8, 0xe9, 0x2c, 0x67, 0x4d, 0x8a, 0x87, 0x22, 0xd1, + 0x65, 0x2f, 0x08, 0xef, 0x01, 0xd9, 0x73, 0x00, 0x2d, 0x00, + 0x02, 0x01, 0x01, 0x00, 0x2b, 0x00, 0x0b, 0x0a, 0x1a, 0x1a, + 0x7f, 0x17, 0x03, 0x03, 0x03, 0x02, 0x03, 0x01, 0x00, 0x0a, + 0x00, 0x0a, 0x00, 0x08, 0xea, 0xea, 0x00, 0x1d, 0x00, 0x17, + 0x00, 0x18, 0x00, 0x1b, 0x00, 0x03, 0x02, 0x00, 0x02, 0xaa, + 0xaa, 0x00, 0x01, 0x00, 0x00, 0x15, 0x00, 0xc7, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + size_t buff2_len = sizeof(buff2) / sizeof(char); + enum parse_chello_result result2; + struct ssl_chello* chello2 = ssl_chello_parse(buff2, buff2_len, &result2); + printf("---------------------------tls1.2 --------------------------------\n"); + printf("record layer version: %d, %d\n", chello2->record_layer_version.major, chello2->record_layer_version.minor); + printf("client hello version: %d, %d\n", chello2->chello_version.major, chello2->chello_version.minor); + printf("cipher suites: %s\n", chello2->cipher_suites); + printf("cipher suites for tls1.3: %s\n", chello2->cipher_suites_tls13); + printf("sni: %s\n", chello2->sni); + char* alpn = parse_alpn(chello2->alpn); + printf("alpn: %s\n", alpn); + free(alpn); + alpn = NULL; + printf("\n\n"); + ssl_chello_free(chello2); + chello2 = NULL; +}