summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/onion_announce.c11
-rw-r--r--toxcore/onion_announce.h2
-rw-r--r--toxcore/onion_client.c141
-rw-r--r--toxcore/onion_client.h2
4 files changed, 133 insertions, 23 deletions
diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c
index feae88a4..c6fbd483 100644
--- a/toxcore/onion_announce.c
+++ b/toxcore/onion_announce.c
@@ -27,7 +27,7 @@
27#include "LAN_discovery.h" 27#include "LAN_discovery.h"
28#include "util.h" 28#include "util.h"
29 29
30#define PING_ID_TIMEOUT 10 30#define PING_ID_TIMEOUT 20
31 31
32#define ANNOUNCE_REQUEST_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES) 32#define ANNOUNCE_REQUEST_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES)
33#define ANNOUNCE_REQUEST_SIZE_RECV (ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3) 33#define ANNOUNCE_REQUEST_SIZE_RECV (ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3)
@@ -135,7 +135,7 @@ static int in_entries(Onion_Announce *onion_a, uint8_t *public_key)
135 return -1; 135 return -1;
136} 136}
137 137
138uint8_t cmp_public_key[crypto_box_PUBLICKEYBYTES]; 138static uint8_t cmp_public_key[crypto_box_PUBLICKEYBYTES];
139static int cmp_entry(const void *a, const void *b) 139static int cmp_entry(const void *a, const void *b)
140{ 140{
141 Onion_Announce_Entry entry1, entry2; 141 Onion_Announce_Entry entry1, entry2;
@@ -237,13 +237,16 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet
237 uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, source.ip.family, 237 uint32_t num_nodes = get_close_nodes(onion_a->dht, plain + ONION_PING_ID_SIZE, nodes_list, source.ip.family,
238 LAN_ip(source.ip) == 0, 1); 238 LAN_ip(source.ip) == 0, 1);
239 239
240 uint32_t i;
241
242 for (i = 0; i < num_nodes; ++i)
243 to_net_family(&nodes_list[i].ip_port.ip);
244
240 uint8_t nonce[crypto_box_NONCEBYTES]; 245 uint8_t nonce[crypto_box_NONCEBYTES];
241 new_nonce(nonce); 246 new_nonce(nonce);
242 247
243 uint8_t pl[ONION_PING_ID_SIZE + sizeof(nodes_list)] = {0}; 248 uint8_t pl[ONION_PING_ID_SIZE + sizeof(nodes_list)] = {0};
244 249
245
246
247 if (!stored) { 250 if (!stored) {
248 memcpy(pl, ping_id2, ONION_PING_ID_SIZE); 251 memcpy(pl, ping_id2, ONION_PING_ID_SIZE);
249 } 252 }
diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h
index e51789e1..5afc9baa 100644
--- a/toxcore/onion_announce.h
+++ b/toxcore/onion_announce.h
@@ -29,7 +29,7 @@
29#define ONION_ANNOUNCE_TIMEOUT 300 29#define ONION_ANNOUNCE_TIMEOUT 300
30#define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES 30#define ONION_PING_ID_SIZE crypto_hash_sha256_BYTES
31 31
32#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + crypto_secretbox_MACBYTES) 32#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES)
33 33
34#define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES + ONION_PING_ID_SIZE + crypto_box_MACBYTES) 34#define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES + ONION_PING_ID_SIZE + crypto_box_MACBYTES)
35#define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES) 35#define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES)
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c
index d2bdeedb..89bd1c5e 100644
--- a/toxcore/onion_client.c
+++ b/toxcore/onion_client.c
@@ -26,15 +26,19 @@
26 26
27#include "onion_client.h" 27#include "onion_client.h"
28#include "util.h" 28#include "util.h"
29#include "LAN_discovery.h"
29 30
30#define ANNOUNCE_TIMEOUT 10 31#define ANNOUNCE_TIMEOUT 10
31 32
33
32/* Creates a sendback for use in an announce request. 34/* Creates a sendback for use in an announce request.
33 * 35 *
34 * num is 0 if we used our secret public key for the announce 36 * num is 0 if we used our secret public key for the announce
35 * num is 1 + friendnum if we use a temporary one. 37 * num is 1 + friendnum if we use a temporary one.
36 * 38 *
37 * Public key is the key we will be sending it to. 39 * Public key is the key we will be sending it to.
40 * ip_port is the ip_port of the node we will be sending
41 * it to.
38 * 42 *
39 * sendback must be at least ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big 43 * sendback must be at least ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big
40 * 44 *
@@ -42,13 +46,15 @@
42 * return 0 on success 46 * return 0 on success
43 * 47 *
44 */ 48 */
45static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, uint8_t *sendback) 49static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, uint8_t *sendback)
46{ 50{
47 uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES]; 51 uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)];
48 uint64_t time = unix_time(); 52 uint64_t time = unix_time();
53 new_nonce(sendback);
49 memcpy(plain, &num, sizeof(uint32_t)); 54 memcpy(plain, &num, sizeof(uint32_t));
50 memcpy(plain + sizeof(uint32_t), &time, sizeof(uint64_t)); 55 memcpy(plain + sizeof(uint32_t), &time, sizeof(uint64_t));
51 memcpy(plain + sizeof(uint32_t) + sizeof(uint64_t), public_key, crypto_box_PUBLICKEYBYTES); 56 memcpy(plain + sizeof(uint32_t) + sizeof(uint64_t), public_key, crypto_box_PUBLICKEYBYTES);
57 memcpy(plain + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, &ip_port, sizeof(IP_Port));
52 58
53 int len = encrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, plain, sizeof(plain), 59 int len = encrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, plain, sizeof(plain),
54 sendback + crypto_secretbox_NONCEBYTES); 60 sendback + crypto_secretbox_NONCEBYTES);
@@ -59,34 +65,37 @@ static int new_sendback(Onion_Client *onion_c, uint32_t num, uint8_t *public_key
59 return 0; 65 return 0;
60} 66}
61 67
62/* Checks if the sendback is valid and returns the public key contained in it in returned_pubkey 68/* Checks if the sendback is valid and returns the public key contained in it in ret_pubkey and the
69 * ip contained in it in ret_ip_port
63 * 70 *
64 * sendback is the sendback ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big 71 * sendback is the sendback ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big
65 * returned_pubkey must be at least crypto_box_PUBLICKEYBYTES big 72 * ret_pubkey must be at least crypto_box_PUBLICKEYBYTES big
73 * ret_ip_port must be at least 1 big
66 * 74 *
67 * return ~0 on failure 75 * return ~0 on failure
68 * return num (see new_sendback(...)) on success 76 * return num (see new_sendback(...)) on success
69 */ 77 */
70static uint32_t check_sendback(Onion_Client *onion_c, uint8_t *sendback, uint8_t *returned_pubkey) 78static uint32_t check_sendback(Onion_Client *onion_c, uint8_t *sendback, uint8_t *ret_pubkey, IP_Port *ret_ip_port)
71{ 79{
72 uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES]; 80 uint8_t plain[sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port)];
73 int len = decrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, sendback + crypto_secretbox_NONCEBYTES, 81 int len = decrypt_data_symmetric(onion_c->secret_symmetric_key, sendback, sendback + crypto_secretbox_NONCEBYTES,
74 ONION_ANNOUNCE_SENDBACK_DATA_LENGTH - crypto_secretbox_NONCEBYTES, plain); 82 ONION_ANNOUNCE_SENDBACK_DATA_LENGTH - crypto_secretbox_NONCEBYTES, plain);
75 83
76 if ((uint32_t)len != sizeof(plain)) 84 if ((uint32_t)len != sizeof(plain))
77 return -1; 85 return ~0;
78 86
79 uint64_t timestamp; 87 uint64_t timestamp;
80 memcpy(&timestamp, plain + sizeof(uint32_t), sizeof(uint64_t)); 88 memcpy(&timestamp, plain + sizeof(uint32_t), sizeof(uint64_t));
81 uint64_t temp_time = unix_time(); 89 uint64_t temp_time = unix_time();
82 90
83 if (timestamp + ANNOUNCE_TIMEOUT < temp_time || temp_time < timestamp) 91 if (timestamp + ANNOUNCE_TIMEOUT < temp_time || temp_time < timestamp)
84 return -1; 92 return ~0;
85 93
86 memcpy(returned_pubkey, plain + sizeof(uint32_t) + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES); 94 memcpy(ret_pubkey, plain + sizeof(uint32_t) + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES);
95 memcpy(ret_ip_port, plain + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(IP_Port));
87 uint32_t num; 96 uint32_t num;
88 memcpy(&num, plain, sizeof(uint32_t)); 97 memcpy(&num, plain, sizeof(uint32_t));
89 return plain[0]; 98 return num;
90} 99}
91 100
92static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, uint8_t *dest_pubkey, 101static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, uint8_t *dest_pubkey,
@@ -97,7 +106,7 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
97 106
98 uint8_t sendback[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; 107 uint8_t sendback[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
99 108
100 if (new_sendback(onion_c, 0, dest_pubkey, sendback) == -1) 109 if (new_sendback(onion_c, 0, dest_pubkey, dest, sendback) == -1)
101 return -1; 110 return -1;
102 111
103 uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0}; 112 uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0};
@@ -124,14 +133,84 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
124 } 133 }
125} 134}
126 135
136static uint8_t cmp_public_key[crypto_box_PUBLICKEYBYTES];
137static int cmp_entry(const void *a, const void *b)
138{
139 Onion_Node entry1, entry2;
140 memcpy(&entry1, a, sizeof(Onion_Node));
141 memcpy(&entry2, b, sizeof(Onion_Node));
142 int t1 = is_timeout(entry1.timestamp, ONION_NODE_TIMEOUT);
143 int t2 = is_timeout(entry2.timestamp, ONION_NODE_TIMEOUT);
144
145 if (t1 && t2)
146 return 0;
147
148 if (t1)
149 return -1;
150
151 if (t2)
152 return 1;
153
154 int close = id_closest(cmp_public_key, entry1.client_id, entry2.client_id);
155
156 if (close == 1)
157 return 1;
158
159 if (close == 2)
160 return -1;
161
162 return 0;
163}
164
127static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, 165static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port,
128 uint8_t *ping_id) 166 uint8_t *ping_id)
129{ 167{
168 if (num > onion_c->num_friends)
169 return -1;
170
171 Onion_Node *list_nodes = NULL;
172 uint8_t *reference_id = NULL;
173
174 if (num == 0) {
175 list_nodes = onion_c->clients_announce_list;
176 reference_id = onion_c->dht->c->self_public_key;
177 } else {
178 list_nodes = onion_c->friends_list[num - 1].clients_list;
179 reference_id = onion_c->friends_list[num - 1].real_client_id;
180 }
181
182 memcpy(cmp_public_key, reference_id, crypto_box_PUBLICKEYBYTES);
183 qsort(list_nodes, MAX_ONION_CLIENTS, sizeof(Onion_Node), cmp_entry);
184
185 int index = -1;
130 186
187 if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT)
188 || id_closest(reference_id, list_nodes[0].client_id, public_key) == 2) {
189 index = 0;
190 }
191
192 uint32_t i;
193
194 for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
195 if (memcmp(list_nodes[i].client_id, public_key, crypto_box_PUBLICKEYBYTES) == 0) {
196 index = i;
197 break;
198 }
199 }
200
201 if (index == -1)
202 return 0;
203
204 memcpy(list_nodes[index].client_id, public_key, CLIENT_ID_SIZE);
205 list_nodes[index].ip_port = ip_port;
206 memcpy(list_nodes[index].ping_id, ping_id, ONION_PING_ID_SIZE);
207 list_nodes[index].timestamp = unix_time();
208 list_nodes[index].last_pinged = 0;
131 return 0; 209 return 0;
132} 210}
133 211
134static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *nodes, uint16_t num_nodes) 212static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *nodes, uint16_t num_nodes,
213 IP_Port source)
135{ 214{
136 if (num > onion_c->num_friends) 215 if (num > onion_c->num_friends)
137 return -1; 216 return -1;
@@ -151,8 +230,15 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n
151 } 230 }
152 231
153 uint32_t i; 232 uint32_t i;
233 int lan_ips_accepted = (LAN_ip(source.ip) == 0);
154 234
155 for (i = 0; i < num_nodes; ++i) { 235 for (i = 0; i < num_nodes; ++i) {
236 to_host_family(&nodes[i].ip_port.ip);
237
238 if (!lan_ips_accepted)
239 if (LAN_ip(nodes[i].ip_port.ip) == 0)
240 continue;
241
156 if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT) 242 if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT)
157 || id_closest(reference_id, list_nodes[0].client_id, nodes[i].client_id) == 2) { 243 || id_closest(reference_id, list_nodes[0].client_id, nodes[i].client_id) == 2) {
158 client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL); 244 client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL);
@@ -175,8 +261,8 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
175 uint16_t num_nodes = (length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) / sizeof(Node_format); 261 uint16_t num_nodes = (length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) / sizeof(Node_format);
176 262
177 uint8_t public_key[crypto_box_PUBLICKEYBYTES]; 263 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
178 264 IP_Port ip_port;
179 uint32_t num = check_sendback(onion_c, packet + 1, public_key); 265 uint32_t num = check_sendback(onion_c, packet + 1, public_key, &ip_port);
180 266
181 if (num > onion_c->num_friends) 267 if (num > onion_c->num_friends)
182 return 1; 268 return 1;
@@ -201,11 +287,11 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
201 if ((uint32_t)len != sizeof(plain)) 287 if ((uint32_t)len != sizeof(plain))
202 return 1; 288 return 1;
203 289
204 //TODO
205 //if (client_add_to_list(onion_c, num, uint8_t *public_key, IP_Port ip_port, plain) == -1)
206 // return 1;
207 290
208 if (client_ping_nodes(onion_c, num, (Node_format *)plain + ONION_PING_ID_SIZE, num_nodes) == -1) 291 if (client_add_to_list(onion_c, num, public_key, ip_port, plain) == -1)
292 return 1;
293
294 if (client_ping_nodes(onion_c, num, (Node_format *)plain + ONION_PING_ID_SIZE, num_nodes, source) == -1)
209 return 1; 295 return 1;
210 296
211 return 0; 297 return 0;
@@ -232,18 +318,37 @@ int random_path(Onion_Client *onion_c, Node_format *nodes)
232 return -1; 318 return -1;
233} 319}
234 320
321uint8_t zero_ping[ONION_PING_ID_SIZE];
235static void do_friend(Onion_Client *onion_c, uint16_t friendnum) 322static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
236{ 323{
237 324
238 325
239} 326}
240 327
328#define ANNOUNCE_INTERVAL_NOT_ANNOUNCED 10
329#define ANNOUNCE_INTERVAL_ANNOUNCED 60
330
241static void do_announce(Onion_Client *onion_c) 331static void do_announce(Onion_Client *onion_c)
242{ 332{
243 uint32_t i; 333 uint32_t i;
334 Onion_Node *list_nodes = onion_c->clients_announce_list;
244 335
245 for (i = 0; i < MAX_ONION_CLIENTS; ++i) { 336 for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
337 if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT))
338 continue;
339
340 uint32_t interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED;
246 341
342 if (memcmp(list_nodes[i].ping_id, zero_ping, ONION_PING_ID_SIZE) == 0) {
343 interval = ANNOUNCE_INTERVAL_ANNOUNCED;
344 }
345
346 if (is_timeout(list_nodes[i].last_pinged, interval)) {
347 if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].client_id,
348 list_nodes[i].ping_id) == 0) {
349 list_nodes[i].last_pinged = unix_time();
350 }
351 }
247 } 352 }
248} 353}
249 354
diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h
index 5becca48..5f205bad 100644
--- a/toxcore/onion_client.h
+++ b/toxcore/onion_client.h
@@ -33,6 +33,8 @@ typedef struct {
33 IP_Port ip_port; 33 IP_Port ip_port;
34 uint8_t ping_id[ONION_PING_ID_SIZE]; 34 uint8_t ping_id[ONION_PING_ID_SIZE];
35 uint64_t timestamp; 35 uint64_t timestamp;
36
37 uint64_t last_pinged;
36} Onion_Node; 38} Onion_Node;
37 39
38typedef struct { 40typedef struct {