Пример #1
0
static int handle_send_2(void *object, IP_Port source, const uint8_t *packet, uint32_t length)
{
    Onion *onion = object;

    if (length > ONION_MAX_PACKET_SIZE)
        return 1;

    if (length <= 1 + SEND_3)
        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_3, 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 + RETURN_2), plain);

    if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2 + crypto_box_MACBYTES))
        return 1;

    IP_Port send_to;
    ipport_unpack(&send_to, plain);
    to_host_family(&send_to.ip);

    uint8_t data[ONION_MAX_PACKET_SIZE];
    memcpy(data, plain + SIZE_IPPORT, len - SIZE_IPPORT);
    uint32_t data_len = (len - SIZE_IPPORT);
    uint8_t *ret_part = data + (len - SIZE_IPPORT);
    new_nonce(ret_part);
    uint8_t ret_data[RETURN_2 + SIZE_IPPORT];
    ipport_pack(ret_data, &source);
    memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2);
    len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
                                 ret_part + crypto_box_NONCEBYTES);

    if (len != RETURN_3 - crypto_box_NONCEBYTES)
        return 1;

    data_len += RETURN_3;

    if ((uint32_t)sendpacket(onion->net, send_to, data, data_len) != data_len)
        return 1;

    return 0;
}
Пример #2
0
static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t length)
{
    Onion_Client *onion_c = object;

    if (length < FAKEID_DATA_MIN_LENGTH)
        return 1;

    if (length > FAKEID_DATA_MAX_LENGTH)
        return 1;

    if ((length - FAKEID_DATA_MIN_LENGTH) % sizeof(Node_format) != 0)
        return 1;

    int friend_num = onion_friend_num(onion_c, source_pubkey);

    if (friend_num == -1)
        return 1;

    if (memcmp(data + 1, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES) != 0) {
        DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id);

        if (DHT_addfriend(onion_c->dht, data + 1) == 1) {
            return 1;
        }

        memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1, crypto_box_PUBLICKEYBYTES);
    }

    uint16_t num_nodes = (length - FAKEID_DATA_MIN_LENGTH) / sizeof(Node_format);
    Node_format nodes[num_nodes];
    memcpy(nodes, data + 1 + crypto_box_PUBLICKEYBYTES, sizeof(nodes));
    uint32_t i;

    for (i = 0; i < num_nodes; ++i) {
        to_host_family(&nodes[i].ip_port.ip);
        DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id);
    }

    //TODO replay protection
    return 0;
}
Пример #3
0
static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *nodes, uint16_t num_nodes,
                             IP_Port source)
{
    if (num > onion_c->num_friends)
        return -1;

    if (num_nodes == 0)
        return 0;

    Onion_Node *list_nodes = NULL;
    uint8_t *reference_id = NULL;

    if (num == 0) {
        list_nodes = onion_c->clients_announce_list;
        reference_id = onion_c->dht->c->self_public_key;
    } else {
        list_nodes = onion_c->friends_list[num - 1].clients_list;
        reference_id = onion_c->friends_list[num - 1].real_client_id;
    }

    uint32_t i;
    int lan_ips_accepted = (LAN_ip(source.ip) == 0);

    for (i = 0; i < num_nodes; ++i) {
        to_host_family(&nodes[i].ip_port.ip);

        if (!lan_ips_accepted)
            if (LAN_ip(nodes[i].ip_port.ip) == 0)
                continue;

        if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT)
                || id_closest(reference_id, list_nodes[0].client_id, nodes[i].client_id) == 2) {
            client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL);
        }
    }

    return 0;
}
Пример #4
0
static int handle_sendnodes(Group_Chat *chat, IP_Port source, int peernum, uint8_t *data, uint32_t len)
{
    if ((uint32_t)peernum >= chat->numpeers)
        return 1;

    if (len > sizeof(sendnodes_data) || len < sizeof(uint64_t))
        return 1;

    if ((len - sizeof(uint64_t)) % sizeof(groupchat_nodes) != 0)
        return 1;

    if (is_timeout(chat->group[peernum].last_pinged, GROUP_PING_TIMEOUT))
        return 1;

    sendnodes_data contents;
    memcpy(&contents, data, len);

    if (contents.pingid != chat->group[peernum].pingid)
        return 1;

    uint16_t numnodes = (len - sizeof(contents.pingid)) / sizeof(groupchat_nodes);
    uint32_t i;

    IPPTs ippts_send;
    ippts_send.timestamp = unix_time();

    for (i = 0; i < numnodes; ++i) {
        if (peer_okping(chat, contents.nodes[i].client_id) > 0) {
            int peern = peer_in_chat(chat, contents.nodes[i].client_id);

            if (peern == -1) { /*NOTE: This is just for testing and will be removed later.*/
                peern = addpeer(chat, contents.nodes[i].client_id);
            }

            if (peern == -1)
                continue;

            to_host_family(&contents.nodes[i].ip_port.ip);
            send_getnodes(chat, contents.nodes[i].ip_port, peern);

            if (chat->assoc) {
                ippts_send.ip_port = contents.nodes[i].ip_port;
                Assoc_add_entry(chat->assoc, contents.nodes[i].client_id, &ippts_send, NULL, 0);
            }
        }
    }

    int ok = add_closepeer(chat, chat->group[peernum].client_id, source);

    if (chat->assoc) {
        ippts_send.ip_port = chat->group[peernum].ping_via;
        ippts_send.timestamp = chat->group[peernum].last_pinged;

        IP_Port ipp_recv;
        ipp_recv = source;

        Assoc_add_entry(chat->assoc, contents.nodes[i].client_id, &ippts_send, &ipp_recv, ok == 0 ? 1 : 0);
    }

    return 0;
}