summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--toxcore/onion.c79
-rw-r--r--toxcore/onion.h29
-rw-r--r--toxcore/onion_announce.c21
-rw-r--r--toxcore/onion_announce.h15
-rw-r--r--toxcore/onion_client.c122
-rw-r--r--toxcore/onion_client.h27
6 files changed, 202 insertions, 91 deletions
diff --git a/toxcore/onion.c b/toxcore/onion.c
index 578621cc..57001784 100644
--- a/toxcore/onion.c
+++ b/toxcore/onion.c
@@ -47,48 +47,81 @@ static void change_symmetric_key(Onion *onion)
47 } 47 }
48} 48}
49 49
50/* Create a new onion path.
51 *
52 * Create a new onion path out of nodes (nodes is a list of 3 nodes)
53 *
54 * new_path must be an empty memory location of atleast Onion_Path size.
55 *
56 * return -1 on failure.
57 * return 0 on success.
58 */
59int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes)
60{
61 if (!new_path || !nodes)
62 return -1;
63
64 encrypt_precompute(nodes[0].client_id, dht->self_secret_key, new_path->shared_key1);
65 memcpy(new_path->public_key1, dht->self_public_key, crypto_box_PUBLICKEYBYTES);
66
67 uint8_t random_public_key[crypto_box_PUBLICKEYBYTES];
68 uint8_t random_secret_key[crypto_box_SECRETKEYBYTES];
69
70 crypto_box_keypair(random_public_key, random_secret_key);
71 encrypt_precompute(nodes[1].client_id, random_secret_key, new_path->shared_key2);
72 memcpy(new_path->public_key2, random_public_key, crypto_box_PUBLICKEYBYTES);
73
74 crypto_box_keypair(random_public_key, random_secret_key);
75 encrypt_precompute(nodes[2].client_id, random_secret_key, new_path->shared_key3);
76 memcpy(new_path->public_key3, random_public_key, crypto_box_PUBLICKEYBYTES);
77
78 new_path->ip_port1 = nodes[0].ip_port;
79 new_path->ip_port2 = nodes[1].ip_port;
80 new_path->ip_port3 = nodes[2].ip_port;
81
82 /* to_net_family(&new_path->ip_port1.ip); */
83 to_net_family(&new_path->ip_port2.ip);
84 to_net_family(&new_path->ip_port3.ip);
85
86 return 0;
87}
88
50/* Create and send a onion packet. 89/* Create and send a onion packet.
51 * 90 *
52 * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data 91 * Use Onion_Path path to send data of length to dest.
53 * with length length will arrive at 3.
54 * 92 *
55 * return -1 on failure. 93 * return -1 on failure.
56 * return 0 on success. 94 * return 0 on success.
57 */ 95 */
58int send_onion_packet(DHT *dht, Node_format *nodes, uint8_t *data, uint32_t length) 96int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length)
59{ 97{
60 if (1 + length + SEND_1 > MAX_ONION_SIZE || length == 0) 98 if (1 + length + SEND_1 > MAX_ONION_SIZE || length == 0)
61 return -1; 99 return -1;
62 100
101 to_net_family(&dest.ip);
63 uint8_t step1[sizeof(IP_Port) + length]; 102 uint8_t step1[sizeof(IP_Port) + length];
64 to_net_family(&nodes[3].ip_port.ip); 103
65 memcpy(step1, &nodes[3].ip_port, sizeof(IP_Port)); 104 memcpy(step1, &dest, sizeof(IP_Port));
66 memcpy(step1 + sizeof(IP_Port), data, length); 105 memcpy(step1 + sizeof(IP_Port), data, length);
67 106
68 uint8_t nonce[crypto_box_NONCEBYTES]; 107 uint8_t nonce[crypto_box_NONCEBYTES];
69 random_nonce(nonce); 108 random_nonce(nonce);
70 uint8_t random_public_key[crypto_box_PUBLICKEYBYTES];
71 uint8_t random_secret_key[crypto_box_SECRETKEYBYTES];
72 crypto_box_keypair(random_public_key, random_secret_key);
73 109
74 uint8_t step2[sizeof(IP_Port) + SEND_BASE + length]; 110 uint8_t step2[sizeof(IP_Port) + SEND_BASE + length];
75 to_net_family(&nodes[2].ip_port.ip); 111 memcpy(step2, &path->ip_port3, sizeof(IP_Port));
76 memcpy(step2, &nodes[2].ip_port, sizeof(IP_Port)); 112 memcpy(step2 + sizeof(IP_Port), path->public_key3, crypto_box_PUBLICKEYBYTES);
77 memcpy(step2 + sizeof(IP_Port), random_public_key, crypto_box_PUBLICKEYBYTES);
78 113
79 int len = encrypt_data(nodes[2].client_id, random_secret_key, nonce, 114 int len = encrypt_data_fast(path->shared_key3, nonce, step1, sizeof(step1),
80 step1, sizeof(step1), step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); 115 step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
81 116
82 if ((uint32_t)len != sizeof(IP_Port) + length + crypto_box_MACBYTES) 117 if ((uint32_t)len != sizeof(IP_Port) + length + crypto_box_MACBYTES)
83 return -1; 118 return -1;
84 119
85 crypto_box_keypair(random_public_key, random_secret_key);
86 uint8_t step3[sizeof(IP_Port) + SEND_BASE * 2 + length]; 120 uint8_t step3[sizeof(IP_Port) + SEND_BASE * 2 + length];
87 to_net_family(&nodes[1].ip_port.ip); 121 memcpy(step3, &path->ip_port2, sizeof(IP_Port));
88 memcpy(step3, &nodes[1].ip_port, sizeof(IP_Port)); 122 memcpy(step3 + sizeof(IP_Port), path->public_key2, crypto_box_PUBLICKEYBYTES);
89 memcpy(step3 + sizeof(IP_Port), random_public_key, crypto_box_PUBLICKEYBYTES); 123 len = encrypt_data_fast(path->shared_key2, nonce, step2, sizeof(step2),
90 len = encrypt_data(nodes[1].client_id, random_secret_key, nonce, 124 step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
91 step2, sizeof(step2), step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES);
92 125
93 if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE + length + crypto_box_MACBYTES) 126 if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE + length + crypto_box_MACBYTES)
94 return -1; 127 return -1;
@@ -96,15 +129,15 @@ int send_onion_packet(DHT *dht, Node_format *nodes, uint8_t *data, uint32_t leng
96 uint8_t packet[1 + length + SEND_1]; 129 uint8_t packet[1 + length + SEND_1];
97 packet[0] = NET_PACKET_ONION_SEND_INITIAL; 130 packet[0] = NET_PACKET_ONION_SEND_INITIAL;
98 memcpy(packet + 1, nonce, crypto_box_NONCEBYTES); 131 memcpy(packet + 1, nonce, crypto_box_NONCEBYTES);
99 memcpy(packet + 1 + crypto_box_NONCEBYTES, dht->self_public_key, crypto_box_PUBLICKEYBYTES); 132 memcpy(packet + 1 + crypto_box_NONCEBYTES, path->public_key1, crypto_box_PUBLICKEYBYTES);
100 133
101 len = encrypt_data(nodes[0].client_id, dht->self_secret_key, nonce, 134 len = encrypt_data_fast(path->shared_key1, nonce, step3, sizeof(step3),
102 step3, sizeof(step3), packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); 135 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
103 136
104 if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES) 137 if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES)
105 return -1; 138 return -1;
106 139
107 if ((uint32_t)sendpacket(dht->c->lossless_udp->net, nodes[0].ip_port, packet, sizeof(packet)) != sizeof(packet)) 140 if ((uint32_t)sendpacket(net, path->ip_port1, packet, sizeof(packet)) != sizeof(packet))
108 return -1; 141 return -1;
109 142
110 return 0; 143 return 0;
diff --git a/toxcore/onion.h b/toxcore/onion.h
index a52bcb86..951a5d1f 100644
--- a/toxcore/onion.h
+++ b/toxcore/onion.h
@@ -41,16 +41,39 @@ typedef struct {
41#define ONION_SEND_2 (crypto_box_NONCEBYTES + ONION_SEND_BASE*2 + ONION_RETURN_1) 41#define ONION_SEND_2 (crypto_box_NONCEBYTES + ONION_SEND_BASE*2 + ONION_RETURN_1)
42#define ONION_SEND_1 (crypto_box_NONCEBYTES + ONION_SEND_BASE*3) 42#define ONION_SEND_1 (crypto_box_NONCEBYTES + ONION_SEND_BASE*3)
43 43
44typedef struct {
45 uint8_t shared_key1[crypto_box_BEFORENMBYTES];
46 uint8_t shared_key2[crypto_box_BEFORENMBYTES];
47 uint8_t shared_key3[crypto_box_BEFORENMBYTES];
48
49 uint8_t public_key1[crypto_box_PUBLICKEYBYTES];
50 uint8_t public_key2[crypto_box_PUBLICKEYBYTES];
51 uint8_t public_key3[crypto_box_PUBLICKEYBYTES];
52
53 IP_Port ip_port1;
54 IP_Port ip_port2;
55 IP_Port ip_port3;
56} Onion_Path;
57
58/* Create a new onion path.
59 *
60 * Create a new onion path out of nodes (nodes is a list of 3 nodes)
61 *
62 * new_path must be an empty memory location of atleast Onion_Path size.
63 *
64 * return -1 on failure.
65 * return 0 on success.
66 */
67int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes);
44 68
45/* Create and send a onion packet. 69/* Create and send a onion packet.
46 * 70 *
47 * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data 71 * Use Onion_Path path to send data of length to dest.
48 * with length length will arrive at 3.
49 * 72 *
50 * return -1 on failure. 73 * return -1 on failure.
51 * return 0 on success. 74 * return 0 on success.
52 */ 75 */
53int send_onion_packet(DHT *dht, Node_format *nodes, uint8_t *data, uint32_t length); 76int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length);
54 77
55/* Create and send a onion response sent initially to dest with. 78/* Create and send a onion response sent initially to dest with.
56 * 79 *
diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c
index 28e27d91..481e995c 100644
--- a/toxcore/onion_announce.c
+++ b/toxcore/onion_announce.c
@@ -37,8 +37,7 @@
37 37
38/* Create and send an onion announce request packet. 38/* Create and send an onion announce request packet.
39 * 39 *
40 * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the announe 40 * path is the path the request will take before it is sent to dest.
41 * request will be sent to 3.
42 * 41 *
43 * public_key and secret_key is the kepair which will be used to encrypt the request. 42 * public_key and secret_key is the kepair which will be used to encrypt the request.
44 * ping_id is the ping id that will be sent in the request. 43 * ping_id is the ping id that will be sent in the request.
@@ -50,8 +49,8 @@
50 * return -1 on failure. 49 * return -1 on failure.
51 * return 0 on success. 50 * return 0 on success.
52 */ 51 */
53int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id, 52int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key,
54 uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data) 53 uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data)
55{ 54{
56 uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; 55 uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
57 memcpy(plain, ping_id, ONION_PING_ID_SIZE); 56 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
63 packet[0] = NET_PACKET_ANNOUNCE_REQUEST; 62 packet[0] = NET_PACKET_ANNOUNCE_REQUEST;
64 random_nonce(packet + 1); 63 random_nonce(packet + 1);
65 64
66 int len = encrypt_data(nodes[3].client_id, secret_key, packet + 1, plain, sizeof(plain), 65 int len = encrypt_data(dest.client_id, secret_key, packet + 1, plain, sizeof(plain),
67 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); 66 packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
68 67
69 if ((uint32_t)len + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES != ANNOUNCE_REQUEST_SIZE) 68 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
71 70
72 memcpy(packet + 1 + crypto_box_NONCEBYTES, public_key, crypto_box_PUBLICKEYBYTES); 71 memcpy(packet + 1 + crypto_box_NONCEBYTES, public_key, crypto_box_PUBLICKEYBYTES);
73 72
74 return send_onion_packet(dht, nodes, packet, sizeof(packet)); 73 return send_onion_packet(net, path, dest.ip_port, packet, sizeof(packet));
75} 74}
76 75
77/* Create and send an onion data request packet. 76/* Create and send an onion data request packet.
78 * 77 *
79 * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data 78 * path is the path the request will take before it is sent to dest.
80 * request packet will arrive at 3. (if 3 knows the person with the public_key they should 79 * (if dest knows the person with the public_key they should
81 * send the packet to that person in the form of a response) 80 * send the packet to that person in the form of a response)
82 * 81 *
83 * public_key is the real public key of the node which we want to send the data of length length to. 82 * 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
88 * return -1 on failure. 87 * return -1 on failure.
89 * return 0 on success. 88 * return 0 on success.
90 */ 89 */
91int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce, 90int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key,
92 uint8_t *data, uint16_t length) 91 uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length)
93{ 92{
94 uint8_t packet[DATA_REQUEST_MIN_SIZE + length]; 93 uint8_t packet[DATA_REQUEST_MIN_SIZE + length];
95 packet[0] = NET_PACKET_ONION_DATA_REQUEST; 94 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
108 if (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + (uint32_t)len != sizeof(packet)) 107 if (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + (uint32_t)len != sizeof(packet))
109 return -1; 108 return -1;
110 109
111 return send_onion_packet(dht, nodes, packet, sizeof(packet)); 110 return send_onion_packet(net, path, dest, packet, sizeof(packet));
112} 111}
113 112
114/* Generate a ping_id and put it in ping_id */ 113/* Generate a ping_id and put it in ping_id */
diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h
index 27b25bd4..24240436 100644
--- a/toxcore/onion_announce.h
+++ b/toxcore/onion_announce.h
@@ -58,8 +58,7 @@ typedef struct {
58 58
59/* Create and send an onion announce request packet. 59/* Create and send an onion announce request packet.
60 * 60 *
61 * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the announe 61 * path is the path the request will take before it is sent to dest.
62 * request will be sent to 3.
63 * 62 *
64 * public_key and secret_key is the kepair which will be used to encrypt the request. 63 * public_key and secret_key is the kepair which will be used to encrypt the request.
65 * ping_id is the ping id that will be sent in the request. 64 * ping_id is the ping id that will be sent in the request.
@@ -71,13 +70,13 @@ typedef struct {
71 * return -1 on failure. 70 * return -1 on failure.
72 * return 0 on success. 71 * return 0 on success.
73 */ 72 */
74int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id, 73int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key,
75 uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data); 74 uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data);
76 75
77/* Create and send an onion data request packet. 76/* Create and send an onion data request packet.
78 * 77 *
79 * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data 78 * path is the path the request will take before it is sent to dest.
80 * request packet will arrive at 3. (if 3 knows the person with the public_key they should 79 * (if dest knows the person with the public_key they should
81 * send the packet to that person in the form of a response) 80 * send the packet to that person in the form of a response)
82 * 81 *
83 * public_key is the real public key of the node which we want to send the data of length length to. 82 * 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
88 * return -1 on failure. 87 * return -1 on failure.
89 * return 0 on success. 88 * return 0 on success.
90 */ 89 */
91int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce, 90int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key,
92 uint8_t *data, uint16_t length); 91 uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length);
93 92
94 93
95Onion_Announce *new_onion_announce(DHT *dht); 94Onion_Announce *new_onion_announce(DHT *dht);
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c
index b3c665b7..6d7785f3 100644
--- a/toxcore/onion_client.c
+++ b/toxcore/onion_client.c
@@ -30,6 +30,63 @@
30 30
31#define ANNOUNCE_TIMEOUT 10 31#define ANNOUNCE_TIMEOUT 10
32 32
33/* Create a new path or use an old suitable one (if pathnum is valid)
34 * or a rondom one from onion_paths.
35 *
36 * return -1 on failure
37 * return 0 on success
38 *
39 * TODO: Make this function better, it currently probably is vulnerable to some attacks that
40 * could de anonimize us.
41 */
42static int random_path(DHT *dht, Onion_Client_Paths *onion_paths, uint32_t pathnum, Onion_Path *path)
43{
44 if (pathnum >= NUMBER_ONION_PATHS)
45 pathnum = rand() % NUMBER_ONION_PATHS;
46
47 if (is_timeout(onion_paths->last_path_success[pathnum], ONION_PATH_TIMEOUT)) {
48 Node_format nodes[3];
49
50 if (random_nodes_path(dht, nodes, 3) != 3)
51 return -1;
52
53 if (create_onion_path(dht, &onion_paths->paths[pathnum], nodes) == -1)
54 return -1;
55
56 onion_paths->last_path_success[pathnum] = unix_time() + ONION_PATH_FIRST_TIMEOUT - ONION_PATH_TIMEOUT;
57 }
58
59 memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path));
60 return 0;
61}
62
63/* Set path timeouts, return the path number.
64 *
65 */
66static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, IP_Port source)
67{
68 if (num > onion_c->num_friends)
69 return -1;
70
71 Onion_Client_Paths *onion_paths;
72
73 if (num == 0) {
74 onion_paths = &onion_c->onion_paths;
75 } else {
76 onion_paths = &onion_c->friends_list[num - 1].onion_paths;
77 }
78
79 uint32_t i;
80
81 for (i = 0; i < NUMBER_ONION_PATHS; ++i) {
82 if (ipport_equal(&onion_paths->paths[i].ip_port1, &source)) {
83 onion_paths->last_path_success[i] = unix_time();
84 return i;
85 }
86 }
87
88 return ~0;
89}
33 90
34/* Creates a sendback for use in an announce request. 91/* Creates a sendback for use in an announce request.
35 * 92 *
@@ -99,7 +156,7 @@ static uint32_t check_sendback(Onion_Client *onion_c, uint8_t *sendback, uint8_t
99} 156}
100 157
101static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, uint8_t *dest_pubkey, 158static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, uint8_t *dest_pubkey,
102 uint8_t *ping_id) 159 uint8_t *ping_id, uint32_t pathnum)
103{ 160{
104 if (num > onion_c->num_friends) 161 if (num > onion_c->num_friends)
105 return -1; 162 return -1;
@@ -114,20 +171,24 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
114 if (ping_id == NULL) 171 if (ping_id == NULL)
115 ping_id = zero_ping_id; 172 ping_id = zero_ping_id;
116 173
117 Node_format nodes[4]; 174 Onion_Path path;
118
119 if (random_path(onion_c, nodes) == -1)
120 return -1;
121 175
122 nodes[3].ip_port = dest; 176 Node_format dest_node;
123 memcpy(nodes[3].client_id, dest_pubkey, crypto_box_PUBLICKEYBYTES); 177 dest_node.ip_port = dest;
178 memcpy(dest_node.client_id, dest_pubkey, crypto_box_PUBLICKEYBYTES);
124 179
125 if (num == 0) { 180 if (num == 0) {
126 return send_announce_request(onion_c->dht, nodes, onion_c->dht->c->self_public_key, 181 if (random_path(onion_c->dht, &onion_c->onion_paths, pathnum, &path) == -1)
182 return -1;
183
184 return send_announce_request(onion_c->net, &path, dest_node, onion_c->dht->c->self_public_key,
127 onion_c->dht->c->self_secret_key, ping_id, 185 onion_c->dht->c->self_secret_key, ping_id,
128 onion_c->dht->c->self_public_key, onion_c->temp_public_key, sendback); 186 onion_c->dht->c->self_public_key, onion_c->temp_public_key, sendback);
129 } else { 187 } else {
130 return send_announce_request(onion_c->dht, nodes, onion_c->friends_list[num - 1].temp_public_key, 188 if (random_path(onion_c->dht, &onion_c->friends_list[num - 1].onion_paths, pathnum, &path) == -1)
189 return -1;
190
191 return send_announce_request(onion_c->net, &path, dest_node, onion_c->friends_list[num - 1].temp_public_key,
131 onion_c->friends_list[num - 1].temp_secret_key, ping_id, 192 onion_c->friends_list[num - 1].temp_secret_key, ping_id,
132 onion_c->friends_list[num - 1].real_client_id, zero_ping_id, sendback); 193 onion_c->friends_list[num - 1].real_client_id, zero_ping_id, sendback);
133 } 194 }
@@ -163,7 +224,7 @@ static int cmp_entry(const void *a, const void *b)
163} 224}
164 225
165static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, 226static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port,
166 uint8_t is_stored, uint8_t *pingid_or_key) 227 uint8_t is_stored, uint8_t *pingid_or_key, IP_Port source)
167{ 228{
168 if (num > onion_c->num_friends) 229 if (num > onion_c->num_friends)
169 return -1; 230 return -1;
@@ -223,7 +284,8 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ
223 284
224 list_nodes[index].is_stored = is_stored; 285 list_nodes[index].is_stored = is_stored;
225 list_nodes[index].timestamp = unix_time(); 286 list_nodes[index].timestamp = unix_time();
226 list_nodes[index].last_pinged = 0; 287 list_nodes[index].last_pinged = unix_time();
288 list_nodes[index].path_used = set_path_timeouts(onion_c, num, source);
227 return 0; 289 return 0;
228} 290}
229 291
@@ -267,7 +329,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n
267 } 329 }
268 330
269 if (j == MAX_ONION_CLIENTS) { 331 if (j == MAX_ONION_CLIENTS) {
270 client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL); 332 client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL, ~0);
271 } 333 }
272 } 334 }
273 } 335 }
@@ -315,7 +377,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
315 return 1; 377 return 1;
316 378
317 379
318 if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1) == -1) 380 if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, source) == -1)
319 return 1; 381 return 1;
320 382
321 Node_format nodes[MAX_SENT_NODES]; 383 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
457 if (list_nodes[i].is_stored) { 519 if (list_nodes[i].is_stored) {
458 Node_format nodes[4]; 520 Node_format nodes[4];
459 521
460 if (random_path(onion_c, nodes) == -1) 522 Onion_Path path;
523
524 if (random_path(onion_c->dht, &onion_c->friends_list[friend_num].onion_paths, ~0, &path) == -1)
461 continue; 525 continue;
462 526
463 memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES); 527 memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES);
464 nodes[3].ip_port = list_nodes[i].ip_port; 528 nodes[3].ip_port = list_nodes[i].ip_port;
465 529
466 if (send_data_request(onion_c->dht, nodes, onion_c->friends_list[friend_num].real_client_id, 530 if (send_data_request(onion_c->net, &path, list_nodes[i].ip_port, onion_c->friends_list[friend_num].real_client_id,
467 list_nodes[i].data_public_key, nonce, packet, sizeof(packet)) == 0) 531 list_nodes[i].data_public_key, nonce, packet, sizeof(packet)) == 0)
468 ++good; 532 ++good;
469 } 533 }
@@ -731,23 +795,6 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on
731 return 0; 795 return 0;
732} 796}
733 797
734/* Takes 3 random nodes that we know and puts them in nodes
735 *
736 * nodes must be longer than 3.
737 *
738 * return -1 on failure
739 * return 0 on success
740 *
741 * TODO: Make this function better, it currently might be vulnerable to some attacks that
742 * could de anonimize us.
743 */
744int random_path(Onion_Client *onion_c, Node_format *nodes)
745{
746 if (random_nodes_path(onion_c->dht, nodes, 3) != 3)
747 return -1;
748
749 return 0;
750}
751 798
752#define ANNOUNCE_FRIEND 30 799#define ANNOUNCE_FRIEND 30
753 800
@@ -770,7 +817,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
770 ++count; 817 ++count;
771 818
772 if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) { 819 if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) {
773 if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0) == 0) { 820 if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0, ~0) == 0) {
774 list_nodes[i].last_pinged = unix_time(); 821 list_nodes[i].last_pinged = unix_time();
775 } 822 }
776 } 823 }
@@ -783,7 +830,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
783 rand() % 2 ? AF_INET : AF_INET6, 1, 0); 830 rand() % 2 ? AF_INET : AF_INET6, 1, 0);
784 831
785 for (i = 0; i < num_nodes; ++i) 832 for (i = 0; i < num_nodes; ++i)
786 client_send_announce_request(onion_c, friendnum + 1, nodes_list[i].ip_port, nodes_list[i].client_id, 0); 833 client_send_announce_request(onion_c, friendnum + 1, nodes_list[i].ip_port, nodes_list[i].client_id, 0, ~0);
787 } 834 }
788 } 835 }
789 836
@@ -845,7 +892,7 @@ static void do_announce(Onion_Client *onion_c)
845 892
846 if (is_timeout(list_nodes[i].last_pinged, interval)) { 893 if (is_timeout(list_nodes[i].last_pinged, interval)) {
847 if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].client_id, 894 if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].client_id,
848 list_nodes[i].ping_id) == 0) { 895 list_nodes[i].ping_id, list_nodes[i].path_used) == 0) {
849 list_nodes[i].last_pinged = unix_time(); 896 list_nodes[i].last_pinged = unix_time();
850 } 897 }
851 } 898 }
@@ -857,8 +904,9 @@ static void do_announce(Onion_Client *onion_c)
857 uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->dht->c->self_public_key, nodes_list, 904 uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->dht->c->self_public_key, nodes_list,
858 rand() % 2 ? AF_INET : AF_INET6, 1, 0); 905 rand() % 2 ? AF_INET : AF_INET6, 1, 0);
859 906
860 for (i = 0; i < num_nodes; ++i) 907 for (i = 0; i < num_nodes; ++i) {
861 client_send_announce_request(onion_c, 0, nodes_list[i].ip_port, nodes_list[i].client_id, 0); 908 client_send_announce_request(onion_c, 0, nodes_list[i].ip_port, nodes_list[i].client_id, 0, ~0);
909 }
862 } 910 }
863 } 911 }
864} 912}
diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h
index 36b5b5c3..d14406a2 100644
--- a/toxcore/onion_client.h
+++ b/toxcore/onion_client.h
@@ -33,6 +33,13 @@
33#define ONION_FAKEID_INTERVAL 30 33#define ONION_FAKEID_INTERVAL 30
34#define DHT_FAKEID_INTERVAL 20 34#define DHT_FAKEID_INTERVAL 20
35 35
36#define NUMBER_ONION_PATHS 3
37
38/* The timeout the first time the path is added and
39 then for all the next consecutive times */
40#define ONION_PATH_FIRST_TIMEOUT 5
41#define ONION_PATH_TIMEOUT 30
42
36typedef struct { 43typedef struct {
37 uint8_t client_id[CLIENT_ID_SIZE]; 44 uint8_t client_id[CLIENT_ID_SIZE];
38 IP_Port ip_port; 45 IP_Port ip_port;
@@ -43,9 +50,16 @@ typedef struct {
43 uint64_t timestamp; 50 uint64_t timestamp;
44 51
45 uint64_t last_pinged; 52 uint64_t last_pinged;
53
54 uint32_t path_used;
46} Onion_Node; 55} Onion_Node;
47 56
48typedef struct { 57typedef struct {
58 Onion_Path paths[NUMBER_ONION_PATHS];
59 uint64_t last_path_success[NUMBER_ONION_PATHS];
60} Onion_Client_Paths;
61
62typedef struct {
49 uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/ 63 uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/
50 uint8_t is_online; /* Set by the onion_set_friend_status function. */ 64 uint8_t is_online; /* Set by the onion_set_friend_status function. */
51 65
@@ -63,6 +77,8 @@ typedef struct {
63 uint64_t last_noreplay; 77 uint64_t last_noreplay;
64 78
65 uint64_t last_seen; 79 uint64_t last_seen;
80
81 Onion_Client_Paths onion_paths;
66} Onion_Friend; 82} Onion_Friend;
67 83
68typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len); 84typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len);
@@ -75,6 +91,8 @@ typedef struct {
75 91
76 Onion_Node clients_announce_list[MAX_ONION_CLIENTS]; 92 Onion_Node clients_announce_list[MAX_ONION_CLIENTS];
77 93
94 Onion_Client_Paths onion_paths;
95
78 uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; 96 uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES];
79 uint64_t last_run; 97 uint64_t last_run;
80 98
@@ -127,15 +145,6 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on
127 */ 145 */
128int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); 146int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port);
129 147
130/* Takes 3 random nodes that we know and puts them in nodes
131 *
132 * nodes must be longer than 3.
133 *
134 * return -1 on failure
135 * return 0 on success
136 *
137 */
138int random_path(Onion_Client *onion_c, Node_format *nodes);
139 148
140/* Send data of length length to friendnum. 149/* Send data of length length to friendnum.
141 * This data will be recieved by the friend using the Onion_Data_Handlers callbacks. 150 * This data will be recieved by the friend using the Onion_Data_Handlers callbacks.