mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Major speed/cpu usage/bandwidth improvements to onion.
This commit is contained in:
parent
b01c19ce56
commit
cebae58ddc
@ -47,48 +47,81 @@ static void change_symmetric_key(Onion *onion)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create and send a onion packet.
|
/* Create a new onion path.
|
||||||
*
|
*
|
||||||
* nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data
|
* Create a new onion path out of nodes (nodes is a list of 3 nodes)
|
||||||
* with length length will arrive at 3.
|
*
|
||||||
|
* new_path must be an empty memory location of atleast Onion_Path size.
|
||||||
*
|
*
|
||||||
* return -1 on failure.
|
* return -1 on failure.
|
||||||
* return 0 on success.
|
* return 0 on success.
|
||||||
*/
|
*/
|
||||||
int send_onion_packet(DHT *dht, Node_format *nodes, uint8_t *data, uint32_t length)
|
int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes)
|
||||||
|
{
|
||||||
|
if (!new_path || !nodes)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
encrypt_precompute(nodes[0].client_id, dht->self_secret_key, new_path->shared_key1);
|
||||||
|
memcpy(new_path->public_key1, dht->self_public_key, crypto_box_PUBLICKEYBYTES);
|
||||||
|
|
||||||
|
uint8_t random_public_key[crypto_box_PUBLICKEYBYTES];
|
||||||
|
uint8_t random_secret_key[crypto_box_SECRETKEYBYTES];
|
||||||
|
|
||||||
|
crypto_box_keypair(random_public_key, random_secret_key);
|
||||||
|
encrypt_precompute(nodes[1].client_id, random_secret_key, new_path->shared_key2);
|
||||||
|
memcpy(new_path->public_key2, random_public_key, crypto_box_PUBLICKEYBYTES);
|
||||||
|
|
||||||
|
crypto_box_keypair(random_public_key, random_secret_key);
|
||||||
|
encrypt_precompute(nodes[2].client_id, random_secret_key, new_path->shared_key3);
|
||||||
|
memcpy(new_path->public_key3, random_public_key, crypto_box_PUBLICKEYBYTES);
|
||||||
|
|
||||||
|
new_path->ip_port1 = nodes[0].ip_port;
|
||||||
|
new_path->ip_port2 = nodes[1].ip_port;
|
||||||
|
new_path->ip_port3 = nodes[2].ip_port;
|
||||||
|
|
||||||
|
/* to_net_family(&new_path->ip_port1.ip); */
|
||||||
|
to_net_family(&new_path->ip_port2.ip);
|
||||||
|
to_net_family(&new_path->ip_port3.ip);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create and send a onion packet.
|
||||||
|
*
|
||||||
|
* Use Onion_Path path to send data of length to dest.
|
||||||
|
*
|
||||||
|
* return -1 on failure.
|
||||||
|
* return 0 on success.
|
||||||
|
*/
|
||||||
|
int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length)
|
||||||
{
|
{
|
||||||
if (1 + length + SEND_1 > MAX_ONION_SIZE || length == 0)
|
if (1 + length + SEND_1 > MAX_ONION_SIZE || length == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
to_net_family(&dest.ip);
|
||||||
uint8_t step1[sizeof(IP_Port) + length];
|
uint8_t step1[sizeof(IP_Port) + length];
|
||||||
to_net_family(&nodes[3].ip_port.ip);
|
|
||||||
memcpy(step1, &nodes[3].ip_port, sizeof(IP_Port));
|
memcpy(step1, &dest, sizeof(IP_Port));
|
||||||
memcpy(step1 + sizeof(IP_Port), data, length);
|
memcpy(step1 + sizeof(IP_Port), data, length);
|
||||||
|
|
||||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||||
random_nonce(nonce);
|
random_nonce(nonce);
|
||||||
uint8_t random_public_key[crypto_box_PUBLICKEYBYTES];
|
|
||||||
uint8_t random_secret_key[crypto_box_SECRETKEYBYTES];
|
|
||||||
crypto_box_keypair(random_public_key, random_secret_key);
|
|
||||||
|
|
||||||
uint8_t step2[sizeof(IP_Port) + SEND_BASE + length];
|
uint8_t step2[sizeof(IP_Port) + SEND_BASE + length];
|
||||||
to_net_family(&nodes[2].ip_port.ip);
|
memcpy(step2, &path->ip_port3, sizeof(IP_Port));
|
||||||
memcpy(step2, &nodes[2].ip_port, sizeof(IP_Port));
|
memcpy(step2 + sizeof(IP_Port), path->public_key3, crypto_box_PUBLICKEYBYTES);
|
||||||
memcpy(step2 + sizeof(IP_Port), random_public_key, crypto_box_PUBLICKEYBYTES);
|
|
||||||
|
|
||||||
int len = encrypt_data(nodes[2].client_id, random_secret_key, nonce,
|
int len = encrypt_data_fast(path->shared_key3, nonce, step1, sizeof(step1),
|
||||||
step1, sizeof(step1), step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
|
step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
|
||||||
|
|
||||||
if ((uint32_t)len != sizeof(IP_Port) + length + crypto_box_MACBYTES)
|
if ((uint32_t)len != sizeof(IP_Port) + length + crypto_box_MACBYTES)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
crypto_box_keypair(random_public_key, random_secret_key);
|
|
||||||
uint8_t step3[sizeof(IP_Port) + SEND_BASE * 2 + length];
|
uint8_t step3[sizeof(IP_Port) + SEND_BASE * 2 + length];
|
||||||
to_net_family(&nodes[1].ip_port.ip);
|
memcpy(step3, &path->ip_port2, sizeof(IP_Port));
|
||||||
memcpy(step3, &nodes[1].ip_port, sizeof(IP_Port));
|
memcpy(step3 + sizeof(IP_Port), path->public_key2, crypto_box_PUBLICKEYBYTES);
|
||||||
memcpy(step3 + sizeof(IP_Port), random_public_key, crypto_box_PUBLICKEYBYTES);
|
len = encrypt_data_fast(path->shared_key2, nonce, step2, sizeof(step2),
|
||||||
len = encrypt_data(nodes[1].client_id, random_secret_key, nonce,
|
step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
|
||||||
step2, sizeof(step2), step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
|
|
||||||
|
|
||||||
if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE + length + crypto_box_MACBYTES)
|
if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE + length + crypto_box_MACBYTES)
|
||||||
return -1;
|
return -1;
|
||||||
@ -96,15 +129,15 @@ int send_onion_packet(DHT *dht, Node_format *nodes, uint8_t *data, uint32_t leng
|
|||||||
uint8_t packet[1 + length + SEND_1];
|
uint8_t packet[1 + length + SEND_1];
|
||||||
packet[0] = NET_PACKET_ONION_SEND_INITIAL;
|
packet[0] = NET_PACKET_ONION_SEND_INITIAL;
|
||||||
memcpy(packet + 1, nonce, crypto_box_NONCEBYTES);
|
memcpy(packet + 1, nonce, crypto_box_NONCEBYTES);
|
||||||
memcpy(packet + 1 + crypto_box_NONCEBYTES, dht->self_public_key, crypto_box_PUBLICKEYBYTES);
|
memcpy(packet + 1 + crypto_box_NONCEBYTES, path->public_key1, crypto_box_PUBLICKEYBYTES);
|
||||||
|
|
||||||
len = encrypt_data(nodes[0].client_id, dht->self_secret_key, nonce,
|
len = encrypt_data_fast(path->shared_key1, nonce, step3, sizeof(step3),
|
||||||
step3, sizeof(step3), packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
|
packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
|
||||||
|
|
||||||
if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES)
|
if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((uint32_t)sendpacket(dht->c->lossless_udp->net, nodes[0].ip_port, packet, sizeof(packet)) != sizeof(packet))
|
if ((uint32_t)sendpacket(net, path->ip_port1, packet, sizeof(packet)) != sizeof(packet))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -41,16 +41,39 @@ typedef struct {
|
|||||||
#define ONION_SEND_2 (crypto_box_NONCEBYTES + ONION_SEND_BASE*2 + ONION_RETURN_1)
|
#define ONION_SEND_2 (crypto_box_NONCEBYTES + ONION_SEND_BASE*2 + ONION_RETURN_1)
|
||||||
#define ONION_SEND_1 (crypto_box_NONCEBYTES + ONION_SEND_BASE*3)
|
#define ONION_SEND_1 (crypto_box_NONCEBYTES + ONION_SEND_BASE*3)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t shared_key1[crypto_box_BEFORENMBYTES];
|
||||||
|
uint8_t shared_key2[crypto_box_BEFORENMBYTES];
|
||||||
|
uint8_t shared_key3[crypto_box_BEFORENMBYTES];
|
||||||
|
|
||||||
/* Create and send a onion packet.
|
uint8_t public_key1[crypto_box_PUBLICKEYBYTES];
|
||||||
|
uint8_t public_key2[crypto_box_PUBLICKEYBYTES];
|
||||||
|
uint8_t public_key3[crypto_box_PUBLICKEYBYTES];
|
||||||
|
|
||||||
|
IP_Port ip_port1;
|
||||||
|
IP_Port ip_port2;
|
||||||
|
IP_Port ip_port3;
|
||||||
|
} Onion_Path;
|
||||||
|
|
||||||
|
/* Create a new onion path.
|
||||||
*
|
*
|
||||||
* nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data
|
* Create a new onion path out of nodes (nodes is a list of 3 nodes)
|
||||||
* with length length will arrive at 3.
|
*
|
||||||
|
* new_path must be an empty memory location of atleast Onion_Path size.
|
||||||
*
|
*
|
||||||
* return -1 on failure.
|
* return -1 on failure.
|
||||||
* return 0 on success.
|
* return 0 on success.
|
||||||
*/
|
*/
|
||||||
int send_onion_packet(DHT *dht, Node_format *nodes, uint8_t *data, uint32_t length);
|
int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes);
|
||||||
|
|
||||||
|
/* Create and send a onion packet.
|
||||||
|
*
|
||||||
|
* Use Onion_Path path to send data of length to dest.
|
||||||
|
*
|
||||||
|
* return -1 on failure.
|
||||||
|
* return 0 on success.
|
||||||
|
*/
|
||||||
|
int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length);
|
||||||
|
|
||||||
/* Create and send a onion response sent initially to dest with.
|
/* Create and send a onion response sent initially to dest with.
|
||||||
*
|
*
|
||||||
|
@ -37,8 +37,7 @@
|
|||||||
|
|
||||||
/* Create and send an onion announce request packet.
|
/* Create and send an onion announce request packet.
|
||||||
*
|
*
|
||||||
* nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the announe
|
* path is the path the request will take before it is sent to dest.
|
||||||
* request will be sent to 3.
|
|
||||||
*
|
*
|
||||||
* public_key and secret_key is the kepair which will be used to encrypt the request.
|
* public_key and secret_key is the kepair which will be used to encrypt the request.
|
||||||
* ping_id is the ping id that will be sent in the request.
|
* ping_id is the ping id that will be sent in the request.
|
||||||
@ -50,8 +49,8 @@
|
|||||||
* return -1 on failure.
|
* return -1 on failure.
|
||||||
* return 0 on success.
|
* return 0 on success.
|
||||||
*/
|
*/
|
||||||
int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id,
|
int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key,
|
||||||
uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data)
|
uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data)
|
||||||
{
|
{
|
||||||
uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
|
uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
|
||||||
memcpy(plain, ping_id, ONION_PING_ID_SIZE);
|
memcpy(plain, ping_id, ONION_PING_ID_SIZE);
|
||||||
@ -63,7 +62,7 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
|
|||||||
packet[0] = NET_PACKET_ANNOUNCE_REQUEST;
|
packet[0] = NET_PACKET_ANNOUNCE_REQUEST;
|
||||||
random_nonce(packet + 1);
|
random_nonce(packet + 1);
|
||||||
|
|
||||||
int len = encrypt_data(nodes[3].client_id, secret_key, packet + 1, plain, sizeof(plain),
|
int len = encrypt_data(dest.client_id, secret_key, packet + 1, plain, sizeof(plain),
|
||||||
packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
|
packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
|
||||||
|
|
||||||
if ((uint32_t)len + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES != ANNOUNCE_REQUEST_SIZE)
|
if ((uint32_t)len + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES != ANNOUNCE_REQUEST_SIZE)
|
||||||
@ -71,13 +70,13 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
|
|||||||
|
|
||||||
memcpy(packet + 1 + crypto_box_NONCEBYTES, public_key, crypto_box_PUBLICKEYBYTES);
|
memcpy(packet + 1 + crypto_box_NONCEBYTES, public_key, crypto_box_PUBLICKEYBYTES);
|
||||||
|
|
||||||
return send_onion_packet(dht, nodes, packet, sizeof(packet));
|
return send_onion_packet(net, path, dest.ip_port, packet, sizeof(packet));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create and send an onion data request packet.
|
/* Create and send an onion data request packet.
|
||||||
*
|
*
|
||||||
* nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data
|
* path is the path the request will take before it is sent to dest.
|
||||||
* request packet will arrive at 3. (if 3 knows the person with the public_key they should
|
* (if dest knows the person with the public_key they should
|
||||||
* send the packet to that person in the form of a response)
|
* send the packet to that person in the form of a response)
|
||||||
*
|
*
|
||||||
* public_key is the real public key of the node which we want to send the data of length length to.
|
* public_key is the real public key of the node which we want to send the data of length length to.
|
||||||
@ -88,8 +87,8 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
|
|||||||
* return -1 on failure.
|
* return -1 on failure.
|
||||||
* return 0 on success.
|
* return 0 on success.
|
||||||
*/
|
*/
|
||||||
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce,
|
int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key,
|
||||||
uint8_t *data, uint16_t length)
|
uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length)
|
||||||
{
|
{
|
||||||
uint8_t packet[DATA_REQUEST_MIN_SIZE + length];
|
uint8_t packet[DATA_REQUEST_MIN_SIZE + length];
|
||||||
packet[0] = NET_PACKET_ONION_DATA_REQUEST;
|
packet[0] = NET_PACKET_ONION_DATA_REQUEST;
|
||||||
@ -108,7 +107,7 @@ int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t
|
|||||||
if (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + (uint32_t)len != sizeof(packet))
|
if (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + (uint32_t)len != sizeof(packet))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return send_onion_packet(dht, nodes, packet, sizeof(packet));
|
return send_onion_packet(net, path, dest, packet, sizeof(packet));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate a ping_id and put it in ping_id */
|
/* Generate a ping_id and put it in ping_id */
|
||||||
|
@ -58,8 +58,7 @@ typedef struct {
|
|||||||
|
|
||||||
/* Create and send an onion announce request packet.
|
/* Create and send an onion announce request packet.
|
||||||
*
|
*
|
||||||
* nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the announe
|
* path is the path the request will take before it is sent to dest.
|
||||||
* request will be sent to 3.
|
|
||||||
*
|
*
|
||||||
* public_key and secret_key is the kepair which will be used to encrypt the request.
|
* public_key and secret_key is the kepair which will be used to encrypt the request.
|
||||||
* ping_id is the ping id that will be sent in the request.
|
* ping_id is the ping id that will be sent in the request.
|
||||||
@ -71,13 +70,13 @@ typedef struct {
|
|||||||
* return -1 on failure.
|
* return -1 on failure.
|
||||||
* return 0 on success.
|
* return 0 on success.
|
||||||
*/
|
*/
|
||||||
int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id,
|
int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key,
|
||||||
uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data);
|
uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data);
|
||||||
|
|
||||||
/* Create and send an onion data request packet.
|
/* Create and send an onion data request packet.
|
||||||
*
|
*
|
||||||
* nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data
|
* path is the path the request will take before it is sent to dest.
|
||||||
* request packet will arrive at 3. (if 3 knows the person with the public_key they should
|
* (if dest knows the person with the public_key they should
|
||||||
* send the packet to that person in the form of a response)
|
* send the packet to that person in the form of a response)
|
||||||
*
|
*
|
||||||
* public_key is the real public key of the node which we want to send the data of length length to.
|
* public_key is the real public key of the node which we want to send the data of length length to.
|
||||||
@ -88,8 +87,8 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
|
|||||||
* return -1 on failure.
|
* return -1 on failure.
|
||||||
* return 0 on success.
|
* return 0 on success.
|
||||||
*/
|
*/
|
||||||
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce,
|
int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key,
|
||||||
uint8_t *data, uint16_t length);
|
uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length);
|
||||||
|
|
||||||
|
|
||||||
Onion_Announce *new_onion_announce(DHT *dht);
|
Onion_Announce *new_onion_announce(DHT *dht);
|
||||||
|
@ -30,6 +30,63 @@
|
|||||||
|
|
||||||
#define ANNOUNCE_TIMEOUT 10
|
#define ANNOUNCE_TIMEOUT 10
|
||||||
|
|
||||||
|
/* Create a new path or use an old suitable one (if pathnum is valid)
|
||||||
|
* or a rondom one from onion_paths.
|
||||||
|
*
|
||||||
|
* return -1 on failure
|
||||||
|
* return 0 on success
|
||||||
|
*
|
||||||
|
* TODO: Make this function better, it currently probably is vulnerable to some attacks that
|
||||||
|
* could de anonimize us.
|
||||||
|
*/
|
||||||
|
static int random_path(DHT *dht, Onion_Client_Paths *onion_paths, uint32_t pathnum, Onion_Path *path)
|
||||||
|
{
|
||||||
|
if (pathnum >= NUMBER_ONION_PATHS)
|
||||||
|
pathnum = rand() % NUMBER_ONION_PATHS;
|
||||||
|
|
||||||
|
if (is_timeout(onion_paths->last_path_success[pathnum], ONION_PATH_TIMEOUT)) {
|
||||||
|
Node_format nodes[3];
|
||||||
|
|
||||||
|
if (random_nodes_path(dht, nodes, 3) != 3)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (create_onion_path(dht, &onion_paths->paths[pathnum], nodes) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
onion_paths->last_path_success[pathnum] = unix_time() + ONION_PATH_FIRST_TIMEOUT - ONION_PATH_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set path timeouts, return the path number.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, IP_Port source)
|
||||||
|
{
|
||||||
|
if (num > onion_c->num_friends)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
Onion_Client_Paths *onion_paths;
|
||||||
|
|
||||||
|
if (num == 0) {
|
||||||
|
onion_paths = &onion_c->onion_paths;
|
||||||
|
} else {
|
||||||
|
onion_paths = &onion_c->friends_list[num - 1].onion_paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < NUMBER_ONION_PATHS; ++i) {
|
||||||
|
if (ipport_equal(&onion_paths->paths[i].ip_port1, &source)) {
|
||||||
|
onion_paths->last_path_success[i] = unix_time();
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ~0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Creates a sendback for use in an announce request.
|
/* Creates a sendback for use in an announce request.
|
||||||
*
|
*
|
||||||
@ -99,7 +156,7 @@ static uint32_t check_sendback(Onion_Client *onion_c, uint8_t *sendback, uint8_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, uint8_t *dest_pubkey,
|
static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, uint8_t *dest_pubkey,
|
||||||
uint8_t *ping_id)
|
uint8_t *ping_id, uint32_t pathnum)
|
||||||
{
|
{
|
||||||
if (num > onion_c->num_friends)
|
if (num > onion_c->num_friends)
|
||||||
return -1;
|
return -1;
|
||||||
@ -114,20 +171,24 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
|
|||||||
if (ping_id == NULL)
|
if (ping_id == NULL)
|
||||||
ping_id = zero_ping_id;
|
ping_id = zero_ping_id;
|
||||||
|
|
||||||
Node_format nodes[4];
|
Onion_Path path;
|
||||||
|
|
||||||
if (random_path(onion_c, nodes) == -1)
|
Node_format dest_node;
|
||||||
return -1;
|
dest_node.ip_port = dest;
|
||||||
|
memcpy(dest_node.client_id, dest_pubkey, crypto_box_PUBLICKEYBYTES);
|
||||||
nodes[3].ip_port = dest;
|
|
||||||
memcpy(nodes[3].client_id, dest_pubkey, crypto_box_PUBLICKEYBYTES);
|
|
||||||
|
|
||||||
if (num == 0) {
|
if (num == 0) {
|
||||||
return send_announce_request(onion_c->dht, nodes, onion_c->dht->c->self_public_key,
|
if (random_path(onion_c->dht, &onion_c->onion_paths, pathnum, &path) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return send_announce_request(onion_c->net, &path, dest_node, onion_c->dht->c->self_public_key,
|
||||||
onion_c->dht->c->self_secret_key, ping_id,
|
onion_c->dht->c->self_secret_key, ping_id,
|
||||||
onion_c->dht->c->self_public_key, onion_c->temp_public_key, sendback);
|
onion_c->dht->c->self_public_key, onion_c->temp_public_key, sendback);
|
||||||
} else {
|
} else {
|
||||||
return send_announce_request(onion_c->dht, nodes, onion_c->friends_list[num - 1].temp_public_key,
|
if (random_path(onion_c->dht, &onion_c->friends_list[num - 1].onion_paths, pathnum, &path) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return send_announce_request(onion_c->net, &path, dest_node, onion_c->friends_list[num - 1].temp_public_key,
|
||||||
onion_c->friends_list[num - 1].temp_secret_key, ping_id,
|
onion_c->friends_list[num - 1].temp_secret_key, ping_id,
|
||||||
onion_c->friends_list[num - 1].real_client_id, zero_ping_id, sendback);
|
onion_c->friends_list[num - 1].real_client_id, zero_ping_id, sendback);
|
||||||
}
|
}
|
||||||
@ -163,7 +224,7 @@ static int cmp_entry(const void *a, const void *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port,
|
static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port,
|
||||||
uint8_t is_stored, uint8_t *pingid_or_key)
|
uint8_t is_stored, uint8_t *pingid_or_key, IP_Port source)
|
||||||
{
|
{
|
||||||
if (num > onion_c->num_friends)
|
if (num > onion_c->num_friends)
|
||||||
return -1;
|
return -1;
|
||||||
@ -223,7 +284,8 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ
|
|||||||
|
|
||||||
list_nodes[index].is_stored = is_stored;
|
list_nodes[index].is_stored = is_stored;
|
||||||
list_nodes[index].timestamp = unix_time();
|
list_nodes[index].timestamp = unix_time();
|
||||||
list_nodes[index].last_pinged = 0;
|
list_nodes[index].last_pinged = unix_time();
|
||||||
|
list_nodes[index].path_used = set_path_timeouts(onion_c, num, source);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +329,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (j == MAX_ONION_CLIENTS) {
|
if (j == MAX_ONION_CLIENTS) {
|
||||||
client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL);
|
client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL, ~0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -315,7 +377,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|
||||||
if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1) == -1)
|
if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, source) == -1)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
Node_format nodes[MAX_SENT_NODES];
|
Node_format nodes[MAX_SENT_NODES];
|
||||||
@ -457,13 +519,15 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32
|
|||||||
if (list_nodes[i].is_stored) {
|
if (list_nodes[i].is_stored) {
|
||||||
Node_format nodes[4];
|
Node_format nodes[4];
|
||||||
|
|
||||||
if (random_path(onion_c, nodes) == -1)
|
Onion_Path path;
|
||||||
|
|
||||||
|
if (random_path(onion_c->dht, &onion_c->friends_list[friend_num].onion_paths, ~0, &path) == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES);
|
memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES);
|
||||||
nodes[3].ip_port = list_nodes[i].ip_port;
|
nodes[3].ip_port = list_nodes[i].ip_port;
|
||||||
|
|
||||||
if (send_data_request(onion_c->dht, nodes, onion_c->friends_list[friend_num].real_client_id,
|
if (send_data_request(onion_c->net, &path, list_nodes[i].ip_port, onion_c->friends_list[friend_num].real_client_id,
|
||||||
list_nodes[i].data_public_key, nonce, packet, sizeof(packet)) == 0)
|
list_nodes[i].data_public_key, nonce, packet, sizeof(packet)) == 0)
|
||||||
++good;
|
++good;
|
||||||
}
|
}
|
||||||
@ -731,23 +795,6 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Takes 3 random nodes that we know and puts them in nodes
|
|
||||||
*
|
|
||||||
* nodes must be longer than 3.
|
|
||||||
*
|
|
||||||
* return -1 on failure
|
|
||||||
* return 0 on success
|
|
||||||
*
|
|
||||||
* TODO: Make this function better, it currently might be vulnerable to some attacks that
|
|
||||||
* could de anonimize us.
|
|
||||||
*/
|
|
||||||
int random_path(Onion_Client *onion_c, Node_format *nodes)
|
|
||||||
{
|
|
||||||
if (random_nodes_path(onion_c->dht, nodes, 3) != 3)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ANNOUNCE_FRIEND 30
|
#define ANNOUNCE_FRIEND 30
|
||||||
|
|
||||||
@ -770,7 +817,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
|
|||||||
++count;
|
++count;
|
||||||
|
|
||||||
if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) {
|
if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) {
|
||||||
if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0) == 0) {
|
if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0, ~0) == 0) {
|
||||||
list_nodes[i].last_pinged = unix_time();
|
list_nodes[i].last_pinged = unix_time();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -783,7 +830,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
|
|||||||
rand() % 2 ? AF_INET : AF_INET6, 1, 0);
|
rand() % 2 ? AF_INET : AF_INET6, 1, 0);
|
||||||
|
|
||||||
for (i = 0; i < num_nodes; ++i)
|
for (i = 0; i < num_nodes; ++i)
|
||||||
client_send_announce_request(onion_c, friendnum + 1, nodes_list[i].ip_port, nodes_list[i].client_id, 0);
|
client_send_announce_request(onion_c, friendnum + 1, nodes_list[i].ip_port, nodes_list[i].client_id, 0, ~0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,7 +892,7 @@ static void do_announce(Onion_Client *onion_c)
|
|||||||
|
|
||||||
if (is_timeout(list_nodes[i].last_pinged, interval)) {
|
if (is_timeout(list_nodes[i].last_pinged, interval)) {
|
||||||
if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].client_id,
|
if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].client_id,
|
||||||
list_nodes[i].ping_id) == 0) {
|
list_nodes[i].ping_id, list_nodes[i].path_used) == 0) {
|
||||||
list_nodes[i].last_pinged = unix_time();
|
list_nodes[i].last_pinged = unix_time();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -857,8 +904,9 @@ static void do_announce(Onion_Client *onion_c)
|
|||||||
uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->dht->c->self_public_key, nodes_list,
|
uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->dht->c->self_public_key, nodes_list,
|
||||||
rand() % 2 ? AF_INET : AF_INET6, 1, 0);
|
rand() % 2 ? AF_INET : AF_INET6, 1, 0);
|
||||||
|
|
||||||
for (i = 0; i < num_nodes; ++i)
|
for (i = 0; i < num_nodes; ++i) {
|
||||||
client_send_announce_request(onion_c, 0, nodes_list[i].ip_port, nodes_list[i].client_id, 0);
|
client_send_announce_request(onion_c, 0, nodes_list[i].ip_port, nodes_list[i].client_id, 0, ~0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,13 @@
|
|||||||
#define ONION_FAKEID_INTERVAL 30
|
#define ONION_FAKEID_INTERVAL 30
|
||||||
#define DHT_FAKEID_INTERVAL 20
|
#define DHT_FAKEID_INTERVAL 20
|
||||||
|
|
||||||
|
#define NUMBER_ONION_PATHS 3
|
||||||
|
|
||||||
|
/* The timeout the first time the path is added and
|
||||||
|
then for all the next consecutive times */
|
||||||
|
#define ONION_PATH_FIRST_TIMEOUT 5
|
||||||
|
#define ONION_PATH_TIMEOUT 30
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t client_id[CLIENT_ID_SIZE];
|
uint8_t client_id[CLIENT_ID_SIZE];
|
||||||
IP_Port ip_port;
|
IP_Port ip_port;
|
||||||
@ -43,8 +50,15 @@ typedef struct {
|
|||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
|
|
||||||
uint64_t last_pinged;
|
uint64_t last_pinged;
|
||||||
|
|
||||||
|
uint32_t path_used;
|
||||||
} Onion_Node;
|
} Onion_Node;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Onion_Path paths[NUMBER_ONION_PATHS];
|
||||||
|
uint64_t last_path_success[NUMBER_ONION_PATHS];
|
||||||
|
} Onion_Client_Paths;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/
|
uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/
|
||||||
uint8_t is_online; /* Set by the onion_set_friend_status function. */
|
uint8_t is_online; /* Set by the onion_set_friend_status function. */
|
||||||
@ -63,6 +77,8 @@ typedef struct {
|
|||||||
uint64_t last_noreplay;
|
uint64_t last_noreplay;
|
||||||
|
|
||||||
uint64_t last_seen;
|
uint64_t last_seen;
|
||||||
|
|
||||||
|
Onion_Client_Paths onion_paths;
|
||||||
} Onion_Friend;
|
} Onion_Friend;
|
||||||
|
|
||||||
typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len);
|
typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len);
|
||||||
@ -75,6 +91,8 @@ typedef struct {
|
|||||||
|
|
||||||
Onion_Node clients_announce_list[MAX_ONION_CLIENTS];
|
Onion_Node clients_announce_list[MAX_ONION_CLIENTS];
|
||||||
|
|
||||||
|
Onion_Client_Paths onion_paths;
|
||||||
|
|
||||||
uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES];
|
uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES];
|
||||||
uint64_t last_run;
|
uint64_t last_run;
|
||||||
|
|
||||||
@ -127,15 +145,6 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on
|
|||||||
*/
|
*/
|
||||||
int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port);
|
int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port);
|
||||||
|
|
||||||
/* Takes 3 random nodes that we know and puts them in nodes
|
|
||||||
*
|
|
||||||
* nodes must be longer than 3.
|
|
||||||
*
|
|
||||||
* return -1 on failure
|
|
||||||
* return 0 on success
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int random_path(Onion_Client *onion_c, Node_format *nodes);
|
|
||||||
|
|
||||||
/* Send data of length length to friendnum.
|
/* Send data of length length to friendnum.
|
||||||
* This data will be recieved by the friend using the Onion_Data_Handlers callbacks.
|
* This data will be recieved by the friend using the Onion_Data_Handlers callbacks.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user