static int handle_send_initial(void *object, IP_Port source, const uint8_t *packet, uint16_t length, void *userdata) { Onion *onion = (Onion *)object; if (length > ONION_MAX_PACKET_SIZE) { return 1; } if (length <= 1 + SEND_1) { return 1; } change_symmetric_key(onion); uint8_t plain[ONION_MAX_PACKET_SIZE]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; get_shared_key(&onion->shared_keys_1, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain); if (len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)) { return 1; } return onion_send_1(onion, plain, len, source, packet + 1); }
/* return 0 on success * return -1 on failure */ static int handle_TCP_packet(TCP_Server *TCP_server, uint32_t con_id, const uint8_t *data, uint16_t length) { if (length == 0) return -1; TCP_Secure_Connection *con = &TCP_server->accepted_connection_array[con_id]; switch (data[0]) { case TCP_PACKET_ROUTING_REQUEST: { if (length != 1 + crypto_box_PUBLICKEYBYTES) return -1; return handle_TCP_routing_req(TCP_server, con_id, data + 1); } case TCP_PACKET_CONNECTION_NOTIFICATION: { if (length != 2) return -1; break; } case TCP_PACKET_DISCONNECT_NOTIFICATION: { if (length != 2) return -1; return rm_connection_index(TCP_server, con, data[1] - NUM_RESERVED_PORTS); } case TCP_PACKET_PING: { if (length != 1 + sizeof(uint64_t)) return -1; uint8_t response[1 + sizeof(uint64_t)]; response[0] = TCP_PACKET_PONG; memcpy(response + 1, data + 1, sizeof(uint64_t)); write_packet_TCP_secure_connection(con, response, sizeof(response)); return 0; } case TCP_PACKET_PONG: { if (length != 1 + sizeof(uint64_t)) return -1; uint64_t ping_id; memcpy(&ping_id, data + 1, sizeof(uint64_t)); if (ping_id) { if (ping_id == con->ping_id) { con->ping_id = 0; } return 0; } else { return -1; } } case TCP_PACKET_OOB_SEND: { if (length <= 1 + crypto_box_PUBLICKEYBYTES) return -1; return handle_TCP_oob_send(TCP_server, con_id, data + 1, data + 1 + crypto_box_PUBLICKEYBYTES, length - (1 + crypto_box_PUBLICKEYBYTES)); } case TCP_PACKET_ONION_REQUEST: { if (TCP_server->onion) { if (length <= 1 + crypto_box_NONCEBYTES + ONION_SEND_BASE * 2) return -1; IP_Port source; source.ip.family = TCP_ONION_FAMILY; source.ip.ip6.uint32[0] = con_id; source.ip.ip6.uint64[1] = con->identifier; onion_send_1(TCP_server->onion, data + 1 + crypto_box_NONCEBYTES, length - (1 + crypto_box_NONCEBYTES), source, data + 1); } return 0; } case TCP_PACKET_ONION_RESPONSE: { return -1; } default: { if (data[0] < NUM_RESERVED_PORTS) return -1; uint8_t c_id = data[0] - NUM_RESERVED_PORTS; if (c_id >= NUM_CLIENT_CONNECTIONS) return -1; if (con->connections[c_id].status == 0) return -1; if (con->connections[c_id].status != 2) return 0; uint32_t index = con->connections[c_id].index; uint8_t other_c_id = con->connections[c_id].other_id + NUM_RESERVED_PORTS; uint8_t new_data[length]; memcpy(new_data, data, length); new_data[0] = other_c_id; int ret = write_packet_TCP_secure_connection(&TCP_server->accepted_connection_array[index], new_data, length); if (ret == -1) return -1; return 0; } } return 0; }