610 lines
22 KiB
C
610 lines
22 KiB
C
|
|
#include "tls1.2_ticket.h"
|
|
#include "list.c"
|
|
|
|
typedef struct tls12_ticket_auth_global_data {
|
|
uint8_t local_client_id[32];
|
|
List client_data;
|
|
time_t startup_time;
|
|
}tls12_ticket_auth_global_data;
|
|
|
|
typedef struct tls12_ticket_auth_local_data {
|
|
int handshake_status;
|
|
char *send_buffer;
|
|
int send_buffer_size;
|
|
char *recv_buffer;
|
|
int recv_buffer_size;
|
|
}tls12_ticket_auth_local_data;
|
|
|
|
void tls12_ticket_auth_local_data_init(tls12_ticket_auth_local_data* local) {
|
|
local->handshake_status = 0;
|
|
local->send_buffer = malloc(0);
|
|
local->send_buffer_size = 0;
|
|
local->recv_buffer = malloc(0);
|
|
local->recv_buffer_size = 0;
|
|
}
|
|
|
|
void * tls12_ticket_auth_init_data() {
|
|
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)malloc(sizeof(tls12_ticket_auth_global_data));
|
|
rand_bytes(global->local_client_id, 32);
|
|
global->client_data = list_init(22);
|
|
global->startup_time = time(NULL);
|
|
return global;
|
|
}
|
|
|
|
obfs * tls12_ticket_auth_new_obfs() {
|
|
obfs * self = new_obfs();
|
|
self->l_data = malloc(sizeof(tls12_ticket_auth_local_data));
|
|
tls12_ticket_auth_local_data_init((tls12_ticket_auth_local_data*)self->l_data);
|
|
return self;
|
|
}
|
|
|
|
void tls12_ticket_auth_dispose(obfs *self) {
|
|
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
|
if (local->send_buffer != NULL) {
|
|
free(local->send_buffer);
|
|
local->send_buffer = NULL;
|
|
}
|
|
if (local->recv_buffer != NULL) {
|
|
free(local->recv_buffer);
|
|
local->recv_buffer = NULL;
|
|
}
|
|
free(local);
|
|
dispose_obfs(self);
|
|
}
|
|
|
|
int tls12_ticket_pack_auth_data(tls12_ticket_auth_global_data *global, server_info *server, char *outdata) {
|
|
int out_size = 32;
|
|
time_t t = time(NULL);
|
|
outdata[0] = t >> 24;
|
|
outdata[1] = t >> 16;
|
|
outdata[2] = t >> 8;
|
|
outdata[3] = t;
|
|
rand_bytes((uint8_t*)outdata + 4, 18);
|
|
|
|
uint8_t *key = (uint8_t*)malloc(server->key_len + 32);
|
|
char hash[ONETIMEAUTH_BYTES * 2];
|
|
memcpy(key, server->key, server->key_len);
|
|
memcpy(key + server->key_len, global->local_client_id, 32);
|
|
ss_sha1_hmac_with_key(hash, outdata, out_size - OBFS_HMAC_SHA1_LEN, key, server->key_len + 32);
|
|
free(key);
|
|
memcpy(outdata + out_size - OBFS_HMAC_SHA1_LEN, hash, OBFS_HMAC_SHA1_LEN);
|
|
return out_size;
|
|
}
|
|
|
|
void tls12_ticket_auth_pack_data(char *encryptdata, int datalength, int start, int len, char *out_buffer, int outlength) {
|
|
out_buffer[outlength] = 0x17;
|
|
out_buffer[outlength + 1] = 0x3;
|
|
out_buffer[outlength + 2] = 0x3;
|
|
out_buffer[outlength + 3] = len >> 8;
|
|
out_buffer[outlength + 4] = len;
|
|
memcpy(out_buffer + outlength + 5, encryptdata + start, len);
|
|
}
|
|
|
|
int tls12_ticket_auth_client_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) {
|
|
char *encryptdata = *pencryptdata;
|
|
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
|
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
|
|
char * out_buffer = NULL;
|
|
|
|
if (local->handshake_status == 8) {
|
|
if (datalength < 1024) {
|
|
if (*capacity < datalength + 5) {
|
|
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + 5) * 2);
|
|
encryptdata = *pencryptdata;
|
|
}
|
|
memmove(encryptdata + 5, encryptdata, datalength);
|
|
encryptdata[0] = 0x17;
|
|
encryptdata[1] = 0x3;
|
|
encryptdata[2] = 0x3;
|
|
encryptdata[3] = datalength >> 8;
|
|
encryptdata[4] = datalength;
|
|
return datalength + 5;
|
|
} else {
|
|
out_buffer = (char*)malloc(datalength + 2048);
|
|
int start = 0;
|
|
int outlength = 0;
|
|
int len;
|
|
while (datalength - start > 2048) {
|
|
len = xorshift128plus() % 4096 + 100;
|
|
if (len > datalength - start)
|
|
len = datalength - start;
|
|
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
|
|
outlength += len + 5;
|
|
start += len;
|
|
}
|
|
if (datalength - start > 0) {
|
|
len = datalength - start;
|
|
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
|
|
outlength += len + 5;
|
|
}
|
|
if (*capacity < outlength) {
|
|
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
|
encryptdata = *pencryptdata;
|
|
}
|
|
memcpy(encryptdata, out_buffer, outlength);
|
|
free(out_buffer);
|
|
return outlength;
|
|
}
|
|
}
|
|
local->send_buffer = (char*)realloc(local->send_buffer, local->send_buffer_size + datalength + 5);
|
|
memcpy(local->send_buffer + local->send_buffer_size + 5, encryptdata, datalength);
|
|
local->send_buffer[local->send_buffer_size] = 0x17;
|
|
local->send_buffer[local->send_buffer_size + 1] = 0x3;
|
|
local->send_buffer[local->send_buffer_size + 2] = 0x3;
|
|
local->send_buffer[local->send_buffer_size + 3] = datalength >> 8;
|
|
local->send_buffer[local->send_buffer_size + 4] = datalength;
|
|
local->send_buffer_size += datalength + 5;
|
|
|
|
if (local->handshake_status == 0) {
|
|
#define CSTR_DECL(name, len, str) const char* name = str; const int len = sizeof(str) - 1;
|
|
CSTR_DECL(tls_data0, tls_data0_len, "\x00\x1c\xc0\x2b\xc0\x2f\xcc\xa9\xcc\xa8\xcc\x14\xcc\x13\xc0\x0a\xc0\x14\xc0\x09\xc0\x13\x00\x9c\x00\x35\x00\x2f\x00\x0a\x01\x00"
|
|
);
|
|
CSTR_DECL(tls_data1, tls_data1_len, "\xff\x01\x00\x01\x00"
|
|
);
|
|
CSTR_DECL(tls_data2, tls_data2_len, "\x00\x17\x00\x00\x00\x23\x00\xd0");
|
|
CSTR_DECL(tls_data3, tls_data3_len, "\x00\x0d\x00\x16\x00\x14\x06\x01\x06\x03\x05\x01\x05\x03\x04\x01\x04\x03\x03\x01\x03\x03\x02\x01\x02\x03\x00\x05\x00\x05\x01\x00\x00\x00\x00\x00\x12\x00\x00\x75\x50\x00\x00\x00\x0b\x00\x02\x01\x00\x00\x0a\x00\x06\x00\x04\x00\x17\x00\x18"
|
|
//"00150066000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" // padding
|
|
);
|
|
uint8_t tls_data[2048];
|
|
int tls_data_len = 0;
|
|
memcpy(tls_data, tls_data1, tls_data1_len);
|
|
tls_data_len += tls_data1_len;
|
|
|
|
char hosts[1024];
|
|
char * phost[128];
|
|
int host_num = 0;
|
|
int pos;
|
|
|
|
char sni[256] = {0};
|
|
if (self->server.param && strlen(self->server.param) == 0)
|
|
self->server.param = NULL;
|
|
strncpy(hosts, self->server.param ? self->server.param : self->server.host, sizeof hosts);
|
|
phost[host_num++] = hosts;
|
|
for (pos = 0; hosts[pos]; ++pos) {
|
|
if (hosts[pos] == ',') {
|
|
phost[host_num++] = &hosts[pos + 1];
|
|
}
|
|
}
|
|
host_num = xorshift128plus() % host_num;
|
|
|
|
sprintf(sni, "%s", phost[host_num]);
|
|
int sni_len = strlen(sni);
|
|
if (sni_len > 0 && sni[sni_len - 1] >= '0' && sni[sni_len - 1] <= '9')
|
|
sni_len = 0;
|
|
tls_data[tls_data_len] = '\0';
|
|
tls_data[tls_data_len + 1] = '\0';
|
|
tls_data[tls_data_len + 2] = (sni_len + 5) >> 8;
|
|
tls_data[tls_data_len + 3] = (sni_len + 5);
|
|
tls_data[tls_data_len + 4] = (sni_len + 3) >> 8;
|
|
tls_data[tls_data_len + 5] = (sni_len + 3);
|
|
tls_data[tls_data_len + 6] = '\0';
|
|
tls_data[tls_data_len + 7] = sni_len >> 8;
|
|
tls_data[tls_data_len + 8] = sni_len;
|
|
memcpy(tls_data + tls_data_len + 9, sni, sni_len);
|
|
tls_data_len += 9 + sni_len;
|
|
memcpy(tls_data + tls_data_len, tls_data2, tls_data2_len);
|
|
tls_data_len += tls_data2_len;
|
|
rand_bytes(tls_data + tls_data_len, 208);
|
|
tls_data_len += 208;
|
|
memcpy(tls_data + tls_data_len, tls_data3, tls_data3_len);
|
|
tls_data_len += tls_data3_len;
|
|
|
|
datalength = 11 + 32 + 1 + 32 + tls_data0_len + 2 + tls_data_len;
|
|
out_buffer = (char*)malloc(datalength);
|
|
char *pdata = out_buffer + datalength - tls_data_len;
|
|
int len = tls_data_len;
|
|
memcpy(pdata, tls_data, tls_data_len);
|
|
pdata[-1] = tls_data_len;
|
|
pdata[-2] = tls_data_len >> 8;
|
|
pdata -= 2; len += 2;
|
|
memcpy(pdata - tls_data0_len, tls_data0, tls_data0_len);
|
|
pdata -= tls_data0_len; len += tls_data0_len;
|
|
memcpy(pdata - 32, global->local_client_id, 32);
|
|
pdata -= 32; len += 32;
|
|
pdata[-1] = 0x20;
|
|
pdata -= 1; len += 1;
|
|
tls12_ticket_pack_auth_data(global, &self->server, pdata - 32);
|
|
pdata -= 32; len += 32;
|
|
pdata[-1] = 0x3;
|
|
pdata[-2] = 0x3; // tls version
|
|
pdata -= 2; len += 2;
|
|
pdata[-1] = len;
|
|
pdata[-2] = len >> 8;
|
|
pdata[-3] = 0;
|
|
pdata[-4] = 1;
|
|
pdata -= 4; len += 4;
|
|
|
|
pdata[-1] = len;
|
|
pdata[-2] = len >> 8;
|
|
pdata -= 2; len += 2;
|
|
pdata[-1] = 0x1;
|
|
pdata[-2] = 0x3; // tls version
|
|
pdata -= 2; len += 2;
|
|
pdata[-1] = 0x16; // tls handshake
|
|
pdata -= 1; len += 1;
|
|
|
|
local->handshake_status = 1;
|
|
} else if (datalength == 0) {
|
|
datalength = local->send_buffer_size + 43;
|
|
out_buffer = (char*)malloc(datalength);
|
|
char *pdata = out_buffer;
|
|
memcpy(pdata, "\x14\x03\x03\x00\x01\x01", 6);
|
|
pdata += 6;
|
|
memcpy(pdata, "\x16\x03\x03\x00\x20", 5);
|
|
pdata += 5;
|
|
rand_bytes((uint8_t*)pdata, 22);
|
|
pdata += 22;
|
|
|
|
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
|
|
char hash[ONETIMEAUTH_BYTES * 2];
|
|
memcpy(key, self->server.key, self->server.key_len);
|
|
memcpy(key + self->server.key_len, global->local_client_id, 32);
|
|
ss_sha1_hmac_with_key(hash, out_buffer, pdata - out_buffer, key, self->server.key_len + 32);
|
|
free(key);
|
|
memcpy(pdata, hash, OBFS_HMAC_SHA1_LEN);
|
|
|
|
pdata += OBFS_HMAC_SHA1_LEN;
|
|
memcpy(pdata, local->send_buffer, local->send_buffer_size);
|
|
free(local->send_buffer);
|
|
local->send_buffer = NULL;
|
|
|
|
local->handshake_status = 8;
|
|
} else {
|
|
return 0;
|
|
}
|
|
if (*capacity < datalength) {
|
|
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = datalength * 2);
|
|
encryptdata = *pencryptdata;
|
|
}
|
|
memmove(encryptdata, out_buffer, datalength);
|
|
free(out_buffer);
|
|
return datalength;
|
|
}
|
|
|
|
int tls12_ticket_auth_server_encode(obfs *self, char **pencryptdata, int datalength, size_t* capacity) {
|
|
char *encryptdata = *pencryptdata;
|
|
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
|
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
|
|
char * out_buffer = NULL;
|
|
|
|
if (local->handshake_status == 8) {
|
|
if (datalength < 1024) {
|
|
if (*capacity < datalength + 5) {
|
|
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + 5) * 2);
|
|
encryptdata = *pencryptdata;
|
|
}
|
|
memmove(encryptdata + 5, encryptdata, datalength);
|
|
encryptdata[0] = 0x17;
|
|
encryptdata[1] = 0x3;
|
|
encryptdata[2] = 0x3;
|
|
encryptdata[3] = datalength >> 8;
|
|
encryptdata[4] = datalength;
|
|
return datalength + 5;
|
|
} else {
|
|
out_buffer = (char*)malloc(datalength + 2048);
|
|
int start = 0;
|
|
int outlength = 0;
|
|
int len;
|
|
while (datalength - start > 2048) {
|
|
len = xorshift128plus() % 4096 + 100;
|
|
if (len > datalength - start)
|
|
len = datalength - start;
|
|
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
|
|
outlength += len + 5;
|
|
start += len;
|
|
}
|
|
if (datalength - start > 0) {
|
|
len = datalength - start;
|
|
tls12_ticket_auth_pack_data(encryptdata, datalength, start, len, out_buffer, outlength);
|
|
outlength += len + 5;
|
|
}
|
|
if (*capacity < outlength) {
|
|
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = outlength * 2);
|
|
encryptdata = *pencryptdata;
|
|
}
|
|
memcpy(encryptdata, out_buffer, outlength);
|
|
free(out_buffer);
|
|
return outlength;
|
|
}
|
|
}
|
|
|
|
local->handshake_status = 3;
|
|
|
|
out_buffer = (char*)malloc(43 + 86);
|
|
int data_len = 0;
|
|
char *p_data = out_buffer + 86;
|
|
|
|
memcpy(p_data - 10, "\xc0\x2f\x00\x00\x05\xff\x01\x00\x01\x00", 10);
|
|
p_data -= 10;data_len += 10;
|
|
|
|
memcpy(p_data - 32, global->local_client_id, 32);
|
|
p_data -= 32;data_len += 32;
|
|
|
|
p_data[-1] = 0x20;
|
|
p_data -= 1;data_len += 1;
|
|
|
|
tls12_ticket_pack_auth_data(global, &self->server, p_data - 32);
|
|
p_data -= 32;data_len += 32;
|
|
|
|
p_data[-1] = 0x3;
|
|
p_data[-2] = 0x3; // tls version
|
|
p_data -= 2;data_len += 2;
|
|
|
|
p_data[-1] = data_len;
|
|
p_data[-2] = data_len >> 8;
|
|
p_data[-3] = 0x00;
|
|
p_data[-4] = 0x02;
|
|
p_data -= 4; data_len += 4;
|
|
|
|
p_data[-1] = data_len;
|
|
p_data[-2] = data_len >> 8;
|
|
p_data[-3] = 0x03;
|
|
p_data[-4] = 0x03;
|
|
p_data[-5] = 0x16;
|
|
p_data -= 5; data_len += 5;
|
|
|
|
memcpy(out_buffer, p_data, data_len);
|
|
char *pdata = out_buffer + 86;
|
|
|
|
memcpy(pdata, "\x14\x03\x03\x00\x01\x01", 6);
|
|
pdata += 6;
|
|
memcpy(pdata, "\x16\x03\x03\x00\x20", 5);
|
|
pdata += 5;
|
|
rand_bytes((uint8_t*)pdata, 22);
|
|
pdata += 22;
|
|
|
|
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
|
|
char hash[ONETIMEAUTH_BYTES * 2];
|
|
memcpy(key, self->server.key, self->server.key_len);
|
|
memcpy(key + self->server.key_len, global->local_client_id, 32);
|
|
ss_sha1_hmac_with_key(hash, out_buffer, 43 + 86, key, self->server.key_len + 32);
|
|
free(key);
|
|
memcpy(pdata, hash, OBFS_HMAC_SHA1_LEN);
|
|
|
|
memmove(encryptdata, out_buffer, 43 + 86);
|
|
free(out_buffer);
|
|
return 43 + 86;
|
|
}
|
|
|
|
int tls12_ticket_auth_client_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) {
|
|
char *encryptdata = *pencryptdata;
|
|
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
|
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
|
|
|
|
*needsendback = 0;
|
|
|
|
if (local->handshake_status == 8) {
|
|
local->recv_buffer_size += datalength;
|
|
local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size);
|
|
memcpy(local->recv_buffer + local->recv_buffer_size - datalength, encryptdata, datalength);
|
|
datalength = 0;
|
|
while (local->recv_buffer_size > 5) {
|
|
if (local->recv_buffer[0] != 0x17)
|
|
return -1;
|
|
int size = ((int)(unsigned char)local->recv_buffer[3] << 8) + (unsigned char)local->recv_buffer[4];
|
|
if (size + 5 > local->recv_buffer_size)
|
|
break;
|
|
if (*capacity < datalength + size) {
|
|
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (datalength + size) * 2);
|
|
encryptdata = *pencryptdata;
|
|
}
|
|
memcpy(encryptdata + datalength, local->recv_buffer + 5, size);
|
|
datalength += size;
|
|
local->recv_buffer_size -= 5 + size;
|
|
memmove(local->recv_buffer, local->recv_buffer + 5 + size, local->recv_buffer_size);
|
|
}
|
|
return datalength;
|
|
}
|
|
if (datalength < 11 + 32 + 1 + 32) {
|
|
return -1;
|
|
}
|
|
|
|
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
|
|
char hash[ONETIMEAUTH_BYTES * 2];
|
|
memcpy(key, self->server.key, self->server.key_len);
|
|
memcpy(key + self->server.key_len, global->local_client_id, 32);
|
|
ss_sha1_hmac_with_key(hash, encryptdata + 11, 22, key, self->server.key_len + 32);
|
|
free(key);
|
|
|
|
if (memcmp(encryptdata + 33, hash, OBFS_HMAC_SHA1_LEN)) {
|
|
return -1;
|
|
}
|
|
|
|
*needsendback = 1;
|
|
return 0;
|
|
}
|
|
|
|
int tls12_ticket_auth_server_decode(obfs *self, char **pencryptdata, int datalength, size_t* capacity, int *needsendback) {
|
|
char *encryptdata = *pencryptdata;
|
|
tls12_ticket_auth_local_data *local = (tls12_ticket_auth_local_data*)self->l_data;
|
|
tls12_ticket_auth_global_data *global = (tls12_ticket_auth_global_data*)self->server.g_data;
|
|
|
|
*needsendback = 0;
|
|
|
|
if (local->handshake_status == 8) {
|
|
if(datalength != 0)
|
|
{
|
|
local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size + datalength);
|
|
memmove(local->recv_buffer + local->recv_buffer_size, encryptdata, datalength);
|
|
local->recv_buffer_size += datalength;
|
|
}
|
|
datalength = 0;
|
|
|
|
while (local->recv_buffer_size > 5) {
|
|
if (local->recv_buffer[0] != 0x17 || local->recv_buffer[1] != 0x03 || local->recv_buffer[2] != 0x03)
|
|
{
|
|
LOGE("server_decode data error, wrong tls version 3");
|
|
return -1;
|
|
}
|
|
int size = ((int)(unsigned char)local->recv_buffer[3] << 8) + (unsigned char)local->recv_buffer[4];
|
|
if (size + 5 > local->recv_buffer_size)
|
|
break;
|
|
if (*capacity < local->recv_buffer_size + size) {
|
|
*pencryptdata = (char*)realloc(*pencryptdata, *capacity = (local->recv_buffer_size + size) * 2);
|
|
encryptdata = *pencryptdata;
|
|
}
|
|
memcpy(encryptdata + datalength, local->recv_buffer + 5, size);
|
|
datalength += size;
|
|
local->recv_buffer_size -= 5 + size;
|
|
memmove(local->recv_buffer, local->recv_buffer + 5 + size, local->recv_buffer_size);
|
|
}
|
|
return datalength;
|
|
}
|
|
|
|
if (local->handshake_status == 3) {
|
|
|
|
char *verify = encryptdata;
|
|
|
|
if(datalength < 43)
|
|
{
|
|
LOGE("server_decode data error, too short:%d", (int)datalength);
|
|
return -1;
|
|
}
|
|
|
|
if(encryptdata[0] != 0x14 || encryptdata[1] != 0x03 || encryptdata[2] != 0x03 || encryptdata[3] != 0x00 || encryptdata[4] != 0x01 || encryptdata[5] != 0x01)
|
|
{
|
|
LOGE("server_decode data error, wrong tls version");
|
|
return -1;
|
|
}
|
|
|
|
encryptdata += 6;
|
|
|
|
if(encryptdata[0] != 0x16 || encryptdata[1] != 0x03 || encryptdata[2] != 0x03 || encryptdata[3] != 0x00 || encryptdata[4] != 0x20)
|
|
{
|
|
LOGE("server_decode data error, wrong tls version 2");
|
|
return -1;
|
|
}
|
|
|
|
uint8_t *key = (uint8_t*)malloc(self->server.key_len + 32);
|
|
char hash[ONETIMEAUTH_BYTES * 2];
|
|
memcpy(key, self->server.key, self->server.key_len);
|
|
memcpy(key + self->server.key_len, global->local_client_id, 32);
|
|
ss_sha1_hmac_with_key(hash, verify, 33, key, self->server.key_len + 32);
|
|
free(key);
|
|
|
|
if (memcmp(verify + 33, hash, OBFS_HMAC_SHA1_LEN) != 0) {
|
|
LOGE("server_decode data error, hash Mismatch %d",(int)memcmp(verify + 33, hash, OBFS_HMAC_SHA1_LEN));
|
|
return -1;
|
|
}
|
|
|
|
local->recv_buffer_size = datalength - 43;
|
|
local->recv_buffer = (char*)realloc(local->recv_buffer, local->recv_buffer_size);
|
|
memmove(local->recv_buffer, encryptdata + 37, datalength - 43);
|
|
|
|
local->handshake_status = 8;
|
|
return tls12_ticket_auth_server_decode(self, pencryptdata, 0, capacity, needsendback);
|
|
}
|
|
|
|
local->handshake_status = 2;
|
|
if(encryptdata[0] != 0x16 || encryptdata[1] != 0x03 || encryptdata[2] != 0x01)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
encryptdata += 3;
|
|
|
|
{
|
|
int size = ((int)(unsigned char)encryptdata[0] << 8) + (unsigned char)encryptdata[1];
|
|
if(size != datalength - 5)
|
|
{
|
|
LOGE("tls_auth wrong tls head size");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
encryptdata += 2;
|
|
|
|
if(encryptdata[0] != 0x01 || encryptdata[1] != 0x00)
|
|
{
|
|
LOGE("tls_auth not client hello message");
|
|
return -1;
|
|
}
|
|
|
|
encryptdata += 2;
|
|
|
|
{
|
|
int size = ((int)(unsigned char)encryptdata[0] << 8) + (unsigned char)encryptdata[1];
|
|
if(size != datalength - 9)
|
|
{
|
|
LOGE("tls_auth wrong message size");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
encryptdata += 2;
|
|
|
|
if(encryptdata[0] != 0x03 || encryptdata[1] != 0x03)
|
|
{
|
|
LOGE("tls_auth wrong tls version");
|
|
return -1;
|
|
}
|
|
|
|
encryptdata += 2;
|
|
|
|
char *verifyid = encryptdata;
|
|
|
|
encryptdata += 32;
|
|
|
|
int sessionid_len = encryptdata[0];
|
|
if(sessionid_len < 32)
|
|
{
|
|
LOGE("tls_auth wrong sessionid_len");
|
|
return -1;
|
|
}
|
|
|
|
char *sessionid = encryptdata + 1;
|
|
memcpy(global->local_client_id , sessionid, sessionid_len);
|
|
|
|
uint8_t *key = (uint8_t*)malloc(self->server.key_len + sessionid_len);
|
|
char hash[ONETIMEAUTH_BYTES * 2];
|
|
memcpy(key, self->server.key, self->server.key_len);
|
|
memcpy(key + self->server.key_len, global->local_client_id, sessionid_len);
|
|
ss_sha1_hmac_with_key(hash, verifyid, 22, key, self->server.key_len + sessionid_len);
|
|
free(key);
|
|
|
|
encryptdata += (sessionid_len + 1);
|
|
|
|
long utc_time = ((int)(unsigned char)verifyid[0] << 24) + ((int)(unsigned char)verifyid[1] << 16) + ((int)(unsigned char)verifyid[2] << 8) + (unsigned char)verifyid[3];
|
|
time_t t = time(NULL);
|
|
|
|
|
|
if (self->server.param && strlen(self->server.param) == 0)
|
|
{
|
|
self->server.param = NULL;
|
|
}
|
|
|
|
int max_time_dif = 0;
|
|
int time_dif = utc_time - t;
|
|
if(self->server.param)
|
|
{
|
|
max_time_dif = atoi(self->server.param);
|
|
}
|
|
|
|
if(max_time_dif > 0 && (time_dif < -max_time_dif || time_dif > max_time_dif || utc_time - global->startup_time < -max_time_dif / 2))
|
|
{
|
|
LOGE("tls_auth wrong time");
|
|
return -1;
|
|
}
|
|
|
|
if (memcmp(verifyid + 22, hash, OBFS_HMAC_SHA1_LEN)) {
|
|
LOGE("tls_auth wrong sha1");
|
|
return -1;
|
|
}
|
|
|
|
int search_result = global->client_data->have_same_cmp(global->client_data, verifyid);
|
|
if(search_result != 0)
|
|
{
|
|
LOGE("replay attack detect!");
|
|
return -1;
|
|
}
|
|
|
|
global->client_data->add_back(global->client_data, verifyid);
|
|
|
|
encryptdata += 48;
|
|
|
|
*needsendback = 1;
|
|
|
|
return 0;
|
|
}
|