From a5da6df1442f0615e727292ab58f90f169e090cf Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 17 May 2014 12:33:22 -0400 Subject: Net_crypto can now handle packets sent as TCP OOB packets. Added timestamp to know which DHT public key is good in case onion_client and net_crypto report different ones. --- toxcore/Messenger.c | 5 ++-- toxcore/net_crypto.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++---- toxcore/net_crypto.h | 5 +++- toxcore/network.h | 1 + toxcore/onion_client.c | 17 ++++++----- toxcore/onion_client.h | 7 +++-- toxcore/tox.c | 2 +- 7 files changed, 97 insertions(+), 20 deletions(-) diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index b5ce2e7e..2c7dcdee 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -2202,8 +2202,9 @@ void do_friends(Messenger *m) friend_new_connection(m, i, m->friendlist[i].client_id); uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; - if (onion_getfriend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key) == 0) { - set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key); + uint64_t timestamp = onion_getfriend_DHT_pubkey(m->onion_c, m->friendlist[i].onion_friendnum, dht_public_key); + if (timestamp != 0) { + set_connection_dht_public_key(m->net_crypto, m->friendlist[i].crypt_connection_id, dht_public_key, timestamp); } uint8_t direct_connected; diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 35cf21cd..2f01bc83 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -233,7 +233,33 @@ static int tcp_handle_cookie_request(Net_Crypto *c, TCP_Client_Connection *TCP_c if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) return -1; - if ((uint32_t)send_data(TCP_con, conn_id, data, sizeof(data)) != 1) + if (send_data(TCP_con, conn_id, data, sizeof(data)) != 1) + return -1; + + return 0; +} + +/* Handle the cookie request packet (for TCP oob packets) + */ +static int tcp_oob_handle_cookie_request(Net_Crypto *c, TCP_Client_Connection *TCP_con, uint8_t *dht_public_key, + uint8_t *packet, uint32_t length) +{ + uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; + uint8_t shared_key[crypto_box_BEFORENMBYTES]; + uint8_t dht_public_key_temp[crypto_box_PUBLICKEYBYTES]; + + if (handle_cookie_request(c, request_plain, shared_key, dht_public_key_temp, packet, length) != 0) + return -1; + + if (memcmp(dht_public_key, dht_public_key_temp, crypto_box_PUBLICKEYBYTES) != 0) + return -1; + + uint8_t data[COOKIE_RESPONSE_LENGTH]; + + if (create_cookie_response(c, data, request_plain, shared_key, dht_public_key) != sizeof(data)) + return -1; + + if (send_oob_packet(TCP_con, dht_public_key, data, sizeof(data)) != 1) return -1; return 0; @@ -1115,7 +1141,7 @@ static int handle_packet_connection(Net_Crypto *c, int crypt_connection_id, uint conn->status = CRYPTO_CONN_NOT_CONFIRMED; /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ - set_connection_dht_public_key(c, crypt_connection_id, dht_public_key); + set_connection_dht_public_key(c, crypt_connection_id, dht_public_key, current_time_monotonic()); } else { return -1; } @@ -1326,7 +1352,7 @@ static int handle_new_connection_handshake(Net_Crypto *c, IP_Port source, uint8_ if (create_send_handshake(c, crypt_connection_id, n_c.cookie, n_c.dht_public_key) == 0) { conn->status = CRYPTO_CONN_NOT_CONFIRMED; /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ - set_connection_dht_public_key(c, crypt_connection_id, n_c.dht_public_key); + set_connection_dht_public_key(c, crypt_connection_id, n_c.dht_public_key, current_time_monotonic()); ret = 0; } } @@ -1375,7 +1401,7 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c) conn->status = CRYPTO_CONN_NOT_CONFIRMED; /* Status needs to be CRYPTO_CONN_NOT_CONFIRMED for this to work. */ - set_connection_dht_public_key(c, crypt_connection_id, n_c->dht_public_key); + set_connection_dht_public_key(c, crypt_connection_id, n_c->dht_public_key, current_time_monotonic()); conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; crypto_connection_add_source(c, crypt_connection_id, n_c->source); return crypt_connection_id; @@ -1463,17 +1489,22 @@ static int connect_peer_tcp(Net_Crypto *c, int crypt_connection_id) } /* Set the DHT public key of the crypto connection. + * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to + * the other peer. * * return -1 on failure. * return 0 on success. */ -int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key) +int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key, uint64_t timestamp) { Crypto_Connection *conn = get_crypto_connection(c, crypt_connection_id); if (conn == 0) return -1; + if (timestamp <= conn->dht_public_key_timestamp) + return -1; + if (conn->dht_public_key_set == 1 && memcmp(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0) return -1; @@ -1483,6 +1514,7 @@ int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_ memcpy(conn->dht_public_key, dht_public_key, crypto_box_PUBLICKEYBYTES); conn->dht_public_key_set = 1; + conn->dht_public_key_timestamp = timestamp; if (conn->status == CRYPTO_CONN_COOKIE_REQUESTING) { conn->cookie_request_number = random_64b(); @@ -1597,6 +1629,43 @@ static int tcp_data_callback(void *object, uint32_t number, uint8_t connection_i return 0; } +static int tcp_oob_callback(void *object, uint8_t *public_key, uint8_t *data, uint16_t length) +{ + if (length == 0 || length > MAX_CRYPTO_PACKET_SIZE) + return -1; + + TCP_Client_Connection *TCP_con = object; + Net_Crypto *c = TCP_con->net_crypto_pointer; + uint32_t location = TCP_con->net_crypto_location; + + if (data[0] == NET_PACKET_COOKIE_REQUEST) { + return tcp_oob_handle_cookie_request(c, TCP_con, public_key, data, length); + } + + int crypt_connection_id = getcryptconnection_id_dht_pubkey(c, public_key); + + if (crypt_connection_id == -1) { + IP_Port source; + source.ip.family = TCP_FAMILY; + source.ip.ip6.uint32[0] = location; + + if (data[0] != NET_PACKET_CRYPTO_HS) { + fprintf(stderr, "tcp snhappen %u\n", data[0]); + return -1; + } + + if (handle_new_connection_handshake(c, source, data, length) != 0) + return -1; + + return 0; + } + + if (handle_packet_connection(c, crypt_connection_id, data, length) != 0) + return -1; + + return 0; +} + /* Check if tcp connection to public key can be created. * * return -1 if it can't. @@ -1696,6 +1765,7 @@ static int add_tcp_connected(Net_Crypto *c, TCP_Client_Connection *tcp_con) routing_response_handler(tcp_con, tcp_response_callback, tcp_con); routing_status_handler(tcp_con, tcp_status_callback, tcp_con); routing_data_handler(tcp_con, tcp_data_callback, tcp_con); + oob_data_handler(tcp_con, tcp_oob_callback, tcp_con); c->tcp_connections[tcp_num] = tcp_con; return 0; } diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index e2e0fffb..dbbb295c 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -92,6 +92,7 @@ typedef struct { uint64_t cookie_request_number; /* number used in the cookie request packets for this connection */ uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; /* The dht public key of the peer */ uint8_t dht_public_key_set; /* True if the dht public key is set, false if it isn't. */ + uint64_t dht_public_key_timestamp; /* Timestamp of the last time we confirmed the key was correct. */ uint8_t *temp_packet; /* Where the cookie request/handshake packet is stored while it is being sent. */ uint16_t temp_packet_length; @@ -186,11 +187,13 @@ int accept_crypto_connection(Net_Crypto *c, New_Connection *n_c); int new_crypto_connection(Net_Crypto *c, uint8_t *real_public_key); /* Set the DHT public key of the crypto connection. + * timestamp is the time (current_time_monotonic()) at which the key was last confirmed belonging to + * the other peer. * * return -1 on failure. * return 0 on success. */ -int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key); +int set_connection_dht_public_key(Net_Crypto *c, int crypt_connection_id, uint8_t *dht_public_key, uint64_t timestamp); /* Set the direct ip of the crypto connection. * diff --git a/toxcore/network.h b/toxcore/network.h index e268df74..f907b9b5 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -154,6 +154,7 @@ typedef int sock_t; #define TCP_ONION_FAMILY (AF_INET6 + 1) #define TCP_INET (AF_INET6 + 2) #define TCP_INET6 (AF_INET6 + 3) +#define TCP_FAMILY (AF_INET6 + 4) typedef union __attribute__ ((__packed__)) { diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 73cb1f75..16333e0c 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -509,6 +509,7 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t } onion_c->friends_list[friend_num].is_fake_clientid = 1; + onion_c->friends_list[friend_num].fake_client_id_timestamp = current_time_monotonic(); memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES); } @@ -814,22 +815,22 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num) /* Copy friends DHT public key into dht_key. * - * return -1 on failure (no key copied). - * return 0 on success (key copied). + * return 0 on failure (no key copied). + * return timestamp on success (key copied). */ -int onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key) +uint64_t onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key) { if ((uint32_t)friend_num >= onion_c->num_friends) - return -1; + return 0; if (onion_c->friends_list[friend_num].status == 0) - return -1; + return 0; if (!onion_c->friends_list[friend_num].is_fake_clientid) - return -1; + return 0; memcpy(dht_key, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES); - return 0; + return onion_c->friends_list[friend_num].fake_client_id_timestamp; } /* Get the ip of friend friendnum and put it in ip_port @@ -843,7 +844,7 @@ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port) { uint8_t dht_public_key[crypto_box_PUBLICKEYBYTES]; - if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) != 0) + if (onion_getfriend_DHT_pubkey(onion_c, friend_num, dht_public_key) == 0) return -1; return DHT_getfriendip(onion_c->dht, dht_public_key, ip_port); diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 06909380..1d56333a 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -82,6 +82,7 @@ typedef struct { uint8_t is_online; /* Set by the onion_set_friend_status function. */ uint8_t is_fake_clientid; /* 0 if we don't know the fake client id of the other 1 if we do. */ + uint64_t fake_client_id_timestamp; uint8_t fake_client_id[crypto_box_PUBLICKEYBYTES]; uint8_t real_client_id[crypto_box_PUBLICKEYBYTES]; @@ -177,10 +178,10 @@ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); /* Copy friends DHT public key into dht_key. * - * return -1 on failure (no key copied). - * return 0 on success (key copied). + * return 0 on failure (no key copied). + * return timestamp on success (key copied). */ -int onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key); +uint64_t onion_getfriend_DHT_pubkey(Onion_Client *onion_c, int friend_num, uint8_t *dht_key); #define ONION_DATA_IN_RESPONSE_MIN_SIZE (crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES) #define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE) diff --git a/toxcore/tox.c b/toxcore/tox.c index d49e2241..d86f1a17 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -721,7 +721,7 @@ int tox_file_send_data(Tox *tox, int32_t friendnumber, uint8_t filenumber, uint8 */ int tox_file_data_size(Tox *tox, int32_t friendnumber) { - return MAX_CRYPTO_DATA_SIZE - 3; + return MAX_CRYPTO_DATA_SIZE - 2; } /* Give the number of bytes left to be sent/received. -- cgit v1.2.3