66 lines
1.8 KiB
C++
66 lines
1.8 KiB
C++
#include "sni_split.h"
|
|
|
|
static bool read_u16(const uint8_t* d, size_t len, size_t pos, uint16_t& out) {
|
|
if (pos + 2 > len) return false;
|
|
out = (uint16_t(d[pos]) << 8) | d[pos + 1];
|
|
return true;
|
|
}
|
|
|
|
size_t find_sni_split_point(const uint8_t* data, size_t len) {
|
|
if (len < 6 || data[0] != 0x16) return 0;
|
|
|
|
size_t pos = 5;
|
|
if (pos >= len || data[pos] != 0x01) return 0;
|
|
pos += 4;
|
|
|
|
if (pos + 2 + 32 > len) return 0;
|
|
pos += 2 + 32;
|
|
|
|
if (pos >= len) return 0;
|
|
uint8_t session_id_len = data[pos];
|
|
pos += 1 + session_id_len;
|
|
|
|
uint16_t cipher_len;
|
|
if (!read_u16(data, len, pos, cipher_len)) return 0;
|
|
pos += 2 + cipher_len;
|
|
|
|
if (pos >= len) return 0;
|
|
uint8_t comp_len = data[pos];
|
|
pos += 1 + comp_len;
|
|
|
|
uint16_t ext_total_len;
|
|
if (!read_u16(data, len, pos, ext_total_len)) return 0;
|
|
pos += 2;
|
|
|
|
size_t ext_end = pos + ext_total_len;
|
|
if (ext_end > len) ext_end = len;
|
|
|
|
while (pos + 4 <= ext_end) {
|
|
uint16_t ext_type, ext_len;
|
|
if (!read_u16(data, len, pos, ext_type)) break;
|
|
if (!read_u16(data, len, pos + 2, ext_len)) break;
|
|
size_t ext_data_start = pos + 4;
|
|
|
|
if (ext_type == 0x0000) {
|
|
size_t p = ext_data_start;
|
|
uint16_t list_len;
|
|
if (!read_u16(data, len, p, list_len)) return 0;
|
|
p += 2;
|
|
if (p + 3 > len) return 0;
|
|
|
|
uint8_t name_type = data[p];
|
|
uint16_t name_len;
|
|
if (name_type != 0 || !read_u16(data, len, p + 1, name_len)) return 0;
|
|
|
|
size_t name_start = p + 3;
|
|
size_t name_end = name_start + name_len;
|
|
if (name_end > len || name_len == 0) return 0;
|
|
|
|
return name_start + (name_len / 2);
|
|
}
|
|
|
|
pos = ext_data_start + ext_len;
|
|
}
|
|
|
|
return 0;
|
|
}
|