fix bugs
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user