Exemplo n.º 1
0
/* handle received packets for not yet established crypto connections. */
static void receive_crypto(void)
{
    uint32_t i;
    for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
        if (crypto_connections[i].status == CONN_HANDSHAKE_SENT) {
            uint8_t temp_data[MAX_DATA_SIZE];
            uint8_t secret_nonce[crypto_box_NONCEBYTES];
            uint8_t public_key[crypto_box_PUBLICKEYBYTES];
            uint8_t session_key[crypto_box_PUBLICKEYBYTES];
            uint16_t len;
            if (id_packet(crypto_connections[i].number) == 1)
                /* if the packet is a friend request drop it (because we are already friends) */
                len = read_packet(crypto_connections[i].number, temp_data);
            if (id_packet(crypto_connections[i].number) == 2) { /* handle handshake packet. */
                len = read_packet(crypto_connections[i].number, temp_data);
                if (handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) {
                    if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) {
                        memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
                        memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
                        increment_nonce(crypto_connections[i].sent_nonce);
                        uint32_t zero = 0;
                        encrypt_precompute(crypto_connections[i].peersessionpublic_key, 
                                           crypto_connections[i].sessionsecret_key, 
                                           crypto_connections[i].shared_key);
                        crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */
                        write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero));
                        crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */
                    }
                }
            } else if (id_packet(crypto_connections[i].number) != -1) // This should not happen kill the connection if it does
                crypto_kill(crypto_connections[i].number);

        }
        if (crypto_connections[i].status == CONN_NOT_CONFIRMED) {
            if (id_packet(crypto_connections[i].number) == 3) {
                uint8_t temp_data[MAX_DATA_SIZE];
                uint8_t data[MAX_DATA_SIZE];
                int length = read_packet(crypto_connections[i].number, temp_data);
                int len = decrypt_data(crypto_connections[i].peersessionpublic_key,
                                       crypto_connections[i].sessionsecret_key,
                                       crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data);
                uint32_t zero = 0;
                if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) {
                    increment_nonce(crypto_connections[i].recv_nonce);
                    encrypt_precompute(crypto_connections[i].peersessionpublic_key, 
                                       crypto_connections[i].sessionsecret_key, 
                                       crypto_connections[i].shared_key);
                    crypto_connections[i].status = CONN_ESTABLISHED;

                    /* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */
                    kill_connection_in(crypto_connections[i].number, 3000000);
                } else
                    crypto_kill(crypto_connections[i].number); // This should not happen kill the connection if it does
            } else if(id_packet(crypto_connections[i].number) != -1)
                /* This should not happen
                   kill the connection if it does */
                crypto_kill(crypto_connections[i].number);
        }
    }
}
Exemplo n.º 2
0
/* Callback for dht public key changes. */
static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key, void *userdata)
{
    Friend_Connections *const fr_c = (Friend_Connections *)object;
    Friend_Conn *const friend_con = get_conn(fr_c, number);

    if (!friend_con) {
        return;
    }

    if (public_key_cmp(friend_con->dht_temp_pk, dht_public_key) == 0) {
        return;
    }

    change_dht_pk(fr_c, number, dht_public_key);

    /* if pk changed, create a new connection.*/
    if (friend_con->crypt_connection_id != -1) {
        crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
        friend_con->crypt_connection_id = -1;
        handle_status(object, number, 0, userdata); /* Going offline. */
    }

    friend_new_connection(fr_c, number);
    onion_set_friend_DHT_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key);
}
Exemplo n.º 3
0
void kill_net_crypto(Net_Crypto *c)
{
    uint32_t i;

    for (i = 0; i < c->crypto_connections_length; ++i) {
        crypto_kill(c, i);
    }

    kill_lossless_udp(c->lossless_udp);
    memset(c, 0, sizeof(Net_Crypto));
    free(c);
}
Exemplo n.º 4
0
/* main friend_connections loop. */
void do_friend_connections(Friend_Connections *fr_c, void *userdata)
{
    const uint64_t temp_time = mono_time_get(fr_c->mono_time);

    for (uint32_t i = 0; i < fr_c->num_cons; ++i) {
        Friend_Conn *const friend_con = get_conn(fr_c, i);

        if (friend_con) {
            if (friend_con->status == FRIENDCONN_STATUS_CONNECTING) {
                if (friend_con->dht_pk_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
                    if (friend_con->dht_lock) {
                        dht_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
                        friend_con->dht_lock = 0;
                        memset(friend_con->dht_temp_pk, 0, CRYPTO_PUBLIC_KEY_SIZE);
                    }
                }

                if (friend_con->dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
                    friend_con->dht_ip_port.ip.family = net_family_unspec;
                }

                if (friend_con->dht_lock) {
                    if (friend_new_connection(fr_c, i) == 0) {
                        set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0);
                        connect_to_saved_tcp_relays(fr_c, i, (MAX_FRIEND_TCP_CONNECTIONS / 2)); /* Only fill it half up. */
                    }
                }
            } else if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) {
                if (friend_con->ping_lastsent + FRIEND_PING_INTERVAL < temp_time) {
                    send_ping(fr_c, i);
                }

                if (friend_con->share_relays_lastsent + SHARE_RELAYS_INTERVAL < temp_time) {
                    send_relays(fr_c, i);
                }

                if (friend_con->ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
                    /* If we stopped receiving ping packets, kill it. */
                    crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
                    friend_con->crypt_connection_id = -1;
                    handle_status(fr_c, i, 0, userdata); /* Going offline. */
                }
            }
        }
    }

    if (fr_c->local_discovery_enabled) {
        lan_discovery(fr_c);
    }
}
Exemplo n.º 5
0
/* main friend_connections loop. */
void do_friend_connections(Friend_Connections *fr_c)
{
    uint32_t i;
    uint64_t temp_time = unix_time();

    for (i = 0; i < fr_c->num_cons; ++i) {
        Friend_Conn *friend_con = get_conn(fr_c, i);

        if (friend_con) {
            if (friend_con->status == FRIENDCONN_STATUS_CONNECTING) {
                if (friend_con->dht_pk_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
                    if (friend_con->dht_lock) {
                        DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
                        friend_con->dht_lock = 0;
                    }
                }

                if (friend_con->dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
                    friend_con->dht_ip_port.ip.family = 0;
                }

                if (friend_con->dht_lock) {
                    if (friend_new_connection(fr_c, i) == 0) {
                        set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0);
                        connect_to_saved_tcp_relays(fr_c, i, (MAX_FRIEND_TCP_CONNECTIONS / 2)); /* Only fill it half up. */
                    }
                }

            } else if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) {
                if (friend_con->ping_lastsent + FRIEND_PING_INTERVAL < temp_time) {
                    send_ping(fr_c, i);
                }

                if (friend_con->share_relays_lastsent + SHARE_RELAYS_INTERVAL < temp_time) {
                    send_relays(fr_c, i);
                }

                if (friend_con->ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
                    /* If we stopped receiving ping packets, kill it. */
                    crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
                    friend_con->crypt_connection_id = -1;
                    handle_status(fr_c, i, 0); /* Going offline. */
                }
            }
        }
    }

    LANdiscovery(fr_c);
}
Exemplo n.º 6
0
/* remove a friend
   return 0 if success
   return -1 if failure */
int m_delfriend(int friendnumber)
{
    if (friendnumber >= numfriends || friendnumber < 0)
        return -1;

    DHT_delfriend(friendlist[friendnumber].client_id);
    crypto_kill(friendlist[friendnumber].crypt_connection_id);
    free(friendlist[friendnumber].userstatus);
    memset(&friendlist[friendnumber], 0, sizeof(Friend));
    uint32_t i;
    for (i = numfriends; i != 0; --i) {
        if (friendlist[i].status != 0)
            break;
    }
    numfriends = i;
    return 0;
}
Exemplo n.º 7
0
static void doInbound(void)
{
    uint8_t secret_nonce[crypto_box_NONCEBYTES];
    uint8_t public_key[crypto_box_PUBLICKEYBYTES];
    uint8_t session_key[crypto_box_PUBLICKEYBYTES];
    int inconnection = crypto_inbound(public_key, secret_nonce, session_key);
    if (inconnection != -1) {
        int friend_id = getfriend_id(public_key);
        if (friend_id != -1) {
            crypto_kill(friendlist[friend_id].crypt_connection_id);
            friendlist[friend_id].crypt_connection_id =
                accept_crypto_inbound(inconnection, public_key, secret_nonce, session_key);

            set_friend_status(friend_id, FRIEND_CONFIRMED);
        }
    }
}
Exemplo n.º 8
0
/* main friend_connections loop. */
void do_friend_connections(Friend_Connections *fr_c)
{
    uint32_t i;
    uint64_t temp_time = unix_time();

    for (i = 0; i < fr_c->num_cons; ++i) {
        Friend_Conn *friend_con = get_conn(fr_c, i);

        if (friend_con) {
            if (friend_con->status == FRIENDCONN_STATUS_CONNECTING) {
                if (friend_con->dht_ping_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
                    if (friend_con->dht_lock) {
                        DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
                        friend_con->dht_lock = 0;
                    }
                }

                if (friend_con->dht_ip_port_lastrecv + FRIEND_DHT_TIMEOUT < temp_time) {
                    friend_con->dht_ip_port.ip.family = 0;
                }

                if (friend_con->dht_lock) {
                    if (friend_new_connection(fr_c, i) == 0) {
                        set_connection_dht_public_key(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_temp_pk);
                        set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port);
                    }
                }

            } else if (friend_con->status == FRIENDCONN_STATUS_CONNECTED) {
                if (friend_con->ping_lastsent + FRIEND_PING_INTERVAL < temp_time) {
                    send_ping(fr_c, i);
                }

                if (friend_con->ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
                    /* If we stopped receiving ping packets, kill it. */
                    crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
                    friend_con->crypt_connection_id = -1;
                    handle_status(fr_c, i, 0); /* Going offline. */
                }
            }
        }
    }
}
Exemplo n.º 9
0
/* remove a friend
   return 0 if success
   return -1 if failure */
int m_delfriend(int friendnumber)
{
    if (friendnumber >= numfriends || friendnumber < 0)
        return -1;

    DHT_delfriend(friendlist[friendnumber].client_id);
    crypto_kill(friendlist[friendnumber].crypt_connection_id);
    free(friendlist[friendnumber].statusmessage);
    memset(&friendlist[friendnumber], 0, sizeof(Friend));
    uint32_t i;

    for (i = numfriends; i != 0; --i) {
        if (friendlist[i-1].status != NOFRIEND)
            break;
    }
    numfriends = i;
    realloc_friendlist(numfriends + 1);

    return 0;
}
Exemplo n.º 10
0
/* Kill a friend connection.
 *
 * return -1 on failure.
 * return 0 on success.
 */
int kill_friend_connection(Friend_Connections *fr_c, int friendcon_id)
{
    Friend_Conn *friend_con = get_conn(fr_c, friendcon_id);

    if (!friend_con)
        return -1;

    if (friend_con->lock_count) {
        --friend_con->lock_count;
        return 0;
    }

    onion_delfriend(fr_c->onion_c, friend_con->onion_friendnum);
    crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);

    if (friend_con->dht_lock) {
        DHT_delfriend(fr_c->dht, friend_con->dht_temp_pk, friend_con->dht_lock);
    }

    return wipe_friend_conn(fr_c, friendcon_id);
}
Exemplo n.º 11
0
/* Callback for dht public key changes. */
static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key)
{
    Friend_Connections *fr_c = object;
    Friend_Conn *friend_con = get_conn(fr_c, number);

    if (!friend_con)
        return;

    if (memcmp(friend_con->dht_temp_pk, dht_public_key, crypto_box_PUBLICKEYBYTES) == 0)
        return;

    change_dht_pk(fr_c, number, dht_public_key);

    /* if pk changed, create a new connection.*/
    if (friend_con->crypt_connection_id != -1) {
        crypto_kill(fr_c->net_crypto, friend_con->crypt_connection_id);
        friend_con->crypt_connection_id = -1;
    }

    friend_new_connection(fr_c, number);
    onion_set_friend_DHT_pubkey(fr_c->onion_c, friend_con->onion_friendnum, dht_public_key);
}
Exemplo n.º 12
0
/* remove a friend
   return 0 if success
   return -1 if failure */
int m_delfriend(Messenger *m, int friendnumber)
{
    if (friendnumber >= m->numfriends || friendnumber < 0)
        return -1;

    DHT_delfriend(m->friendlist[friendnumber].client_id);
    crypto_kill(m->friendlist[friendnumber].crypt_connection_id);
    free(m->friendlist[friendnumber].statusmessage);
    memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend));
    uint32_t i;

    for (i = m->numfriends; i != 0; --i) {
        if (m->friendlist[i - 1].status != NOFRIEND)
            break;
    }

    m->numfriends = i;

    if (realloc_friendlist(m, m->numfriends) != 0)
        return FAERR_NOMEM;

    return 0;
}
Exemplo n.º 13
0
int main(int argc, char *argv[])
{
    if (argc < 4) {
        printf("usage %s ip port filename(of file to send)\n", argv[0]);
        exit(0);
    }
    new_keys();
    printf("OUR ID: ");
    uint32_t i;
    for(i = 0; i < 32; i++) {
        if(self_public_key[i] < 16)
            printf("0");
        printf("%hhX",self_public_key[i]);
    }
    printf("\n");
    
    memcpy(self_client_id, self_public_key, 32);
    
    char temp_id[128];
    printf("Enter the client_id of the friend to connect to (32 bytes HEX format):\n");
    scanf("%s", temp_id);
    
    uint8_t friend_id[32];
    memcpy(friend_id, hex_string_to_bin(temp_id), 32);
    
    /* memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32); */
    

    DHT_addfriend(friend_id);
    IP_Port friend_ip;
    int connection = -1;
    int inconnection = -1;
    
    uint8_t acceptedfriend_public_key[crypto_box_PUBLICKEYBYTES];
    int friendrequest = -1;
    uint8_t request_data[512];
    
    /* initialize networking
     * bind to ip 0.0.0.0:PORT */
    IP ip;
    ip.i = 0;
    init_networking(ip, PORT);
    initNetCrypto();
    
    perror("Initialization");
    IP_Port bootstrap_ip_port;
    bootstrap_ip_port.port = htons(atoi(argv[2]));
    bootstrap_ip_port.ip.i = inet_addr(argv[1]);
    DHT_bootstrap(bootstrap_ip_port);
    
    IP_Port ip_port;
    uint8_t data[MAX_UDP_PACKET_SIZE];
    uint32_t length;
    
    uint8_t buffer1[128];
    int read1 = 0;
    uint8_t buffer2[128];
    int read2 = 0;
    FILE *file1 = fopen(argv[3], "rb");
    if ( file1==NULL ){printf("Error opening file.\n");return 1;}
    FILE *file2 = fopen("received.txt", "wb");
    if ( file2==NULL ){return 1;}
    read1 = fread(buffer1, 1, 128, file1);
    
    while(1) {
        while(receivepacket(&ip_port, data, &length) != -1) {
            if(rand() % 3 != 1) { /* simulate packet loss */
                if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port)) {
                    /* if packet is not recognized */
                    printf("Received unhandled packet with length: %u\n", length);
                } else {
                    printf("Received handled packet with length: %u\n", length);
                }
            }
        }
        friend_ip = DHT_getfriendip(friend_id);
        if(friend_ip.ip.i != 0) {
            if(connection == -1 && friendrequest == -1) {
                printf("Sending friend request to peer:");
                printip(friend_ip);
                friendrequest = send_friendrequest(friend_id, friend_ip,(uint8_t *) "Hello World", 12);
                /* connection = crypto_connect((uint8_t *)friend_id, friend_ip); */
                /* connection = new_connection(friend_ip); */
            }
            if(check_friendrequest(friendrequest) == 1) {
                printf("Started connecting to friend:");
                connection = crypto_connect(friend_id, friend_ip);
            }
        }
        if(inconnection == -1) {
            uint8_t secret_nonce[crypto_box_NONCEBYTES];
            uint8_t public_key[crypto_box_PUBLICKEYBYTES];
            uint8_t session_key[crypto_box_PUBLICKEYBYTES];
            inconnection = crypto_inbound(public_key, secret_nonce, session_key);
            inconnection = accept_crypto_inbound(inconnection, acceptedfriend_public_key, secret_nonce, session_key);
            /* inconnection = incoming_connection(); */
            if(inconnection != -1) {
                printf("Someone connected to us:\n");
               /* printip(connection_ip(inconnection)); */
            }
        }
        if(handle_friendrequest(acceptedfriend_public_key, request_data) > 1) {
            printf("RECIEVED FRIEND REQUEST: %s\n", request_data);
        }

        /* if someone connected to us write what he sends to a file
         * also send him our file. */
        if(inconnection != -1) {
            if(write_cryptpacket(inconnection, buffer1, read1)) {
                printf("Wrote data1.\n");
                read1 = fread(buffer1, 1, 128, file1);
            }
            read2 = read_cryptpacket(inconnection, buffer2);
            if(read2 != 0) {
                printf("Received data1.\n");
                if(!fwrite(buffer2, read2, 1, file2)) {
                        printf("file write error1\n");
                }
                if(read2 < 128) {
                    printf("Closed file1 %u\n", read2);
                    fclose(file2);
                }
            }
            /* if buffer is empty and the connection timed out. */
            else if(is_cryptoconnected(inconnection) == 4) {
                crypto_kill(inconnection);
            }
        }
        /* if we are connected to a friend send him data from the file.
         * also put what he sends us in a file. */
        if(is_cryptoconnected(connection) >= 3)  {
            if(write_cryptpacket(0, buffer1, read1)) {
                printf("Wrote data2.\n");
                read1 = fread(buffer1, 1, 128, file1);
            }
            read2 = read_cryptpacket(0, buffer2);
            if(read2 != 0) {
                printf("Received data2.\n");
                if(!fwrite(buffer2, read2, 1, file2)) {
                        printf("file write error2\n");
                }
                if(read2 < 128) {
                    printf("Closed file2 %u\n", read2);
                    fclose(file2);
                }
            }
            /* if buffer is empty and the connection timed out. */
            else if(is_cryptoconnected(connection) == 4) {
                crypto_kill(connection);
            }
        }
        doDHT();
        doLossless_UDP();
        doNetCrypto();
        /*print_clientlist();
         *print_friendlist();
         *c_sleep(300); */
        c_sleep(1);
    }
    
    shutdown_networking();
    return 0;   
}
Exemplo n.º 14
0
//TODO: make this function not suck.
static void doFriends(void)
{
    /* TODO: add incoming connections and some other stuff. */
    uint32_t i;
    int len;
    uint8_t temp[MAX_DATA_SIZE];
    for (i = 0; i < numfriends; ++i) {
        if (friendlist[i].status == FRIEND_ADDED) {
            int fr = send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size);
            if (fr == 0) /* TODO: This needs to be fixed so that it sends the friend requests a couple of times in case of packet loss */
                set_friend_status(i, FRIEND_REQUESTED);
            else if (fr > 0)
                set_friend_status(i, FRIEND_REQUESTED);
        }
        if (friendlist[i].status == FRIEND_REQUESTED || friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online */
            if (friendlist[i].status == FRIEND_REQUESTED) {
                if (friendlist[i].friend_request_id + 10 < unix_time()) { /*I know this is hackish but it should work.*/
                    send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size);
                    friendlist[i].friend_request_id = unix_time();
                }
            }
            IP_Port friendip = DHT_getfriendip(friendlist[i].client_id);
            switch (is_cryptoconnected(friendlist[i].crypt_connection_id)) {
            case 0:
                if (friendip.ip.i > 1)
                    friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip);
                break;
            case 3: /*  Connection is established */
                set_friend_status(i, FRIEND_ONLINE);
                friendlist[i].name_sent = 0;
                friendlist[i].userstatus_sent = 0;
                friendlist[i].statusmessage_sent = 0;
                break;
            case 4:
                crypto_kill(friendlist[i].crypt_connection_id);
                friendlist[i].crypt_connection_id = -1;
                break;
            default:
                break;
            }
        }
        while (friendlist[i].status == FRIEND_ONLINE) { /* friend is online */
            if (friendlist[i].name_sent == 0) {
                if (m_sendname(i, self_name, self_name_length))
                    friendlist[i].name_sent = 1;
            }
            if (friendlist[i].statusmessage_sent == 0) {
                if (send_statusmessage(i, self_statusmessage, self_statusmessage_length))
                    friendlist[i].statusmessage_sent = 1;
            }
            if (friendlist[i].userstatus_sent == 0) {
                if (send_userstatus(i, self_userstatus))
                    friendlist[i].userstatus_sent = 1;
            }
            len = read_cryptpacket(friendlist[i].crypt_connection_id, temp);
            uint8_t packet_id = temp[0];
            uint8_t* data = temp + 1;
            int data_length = len - 1;
            if (len > 0) {
                switch (packet_id) {
                case PACKET_ID_NICKNAME: {
                    if (data_length >= MAX_NAME_LENGTH || data_length == 0)
                        break;
                    if(friend_namechange_isset)
                        friend_namechange(i, data, data_length);
                    memcpy(friendlist[i].name, data, data_length);
                    friendlist[i].name[data_length - 1] = 0; /* make sure the NULL terminator is present. */
                    break;
                }
                case PACKET_ID_STATUSMESSAGE: {
                    if (data_length == 0)
                        break;
                    uint8_t *status = calloc(MIN(data_length, MAX_STATUSMESSAGE_LENGTH), 1);
                    memcpy(status, data, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));
                    if (friend_statusmessagechange_isset)
                        friend_statusmessagechange(i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));
                    set_friend_statusmessage(i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));
                    free(status);
                    break;
                }
                case PACKET_ID_USERSTATUS: {
                    if (data_length != 1)
                        break;
                    USERSTATUS status = data[0];
                    if (friend_userstatuschange_isset)
                        friend_userstatuschange(i, status);
                    set_friend_userstatus(i, status);
                    break;
                }
                case PACKET_ID_MESSAGE: {
                    uint8_t *message_id = data;
                    uint8_t message_id_length = 4;
                    uint8_t *message = data + message_id_length;
                    uint16_t message_length = data_length - message_id_length;
                    if (friendlist[i].receives_read_receipts) {
                        write_cryptpacket_id(i, PACKET_ID_RECEIPT, message_id, message_id_length);
                    }
                    if (friend_message_isset)
                        (*friend_message)(i, message, message_length);
                    break;
                }
                case PACKET_ID_ACTION: {
                    if (friend_action_isset)
                        (*friend_action)(i, data, data_length);
                    break;
                }
                case PACKET_ID_RECEIPT: {
                    uint32_t msgid;
                    if (data_length < sizeof(msgid))
                        break;
                    memcpy(&msgid, data, sizeof(msgid));
                    msgid = ntohl(msgid);
                    if (read_receipt_isset)
                        (*read_receipt)(i, msgid);
                    break;
                }
                }
            } else {
                if (is_cryptoconnected(friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */
                    crypto_kill(friendlist[i].crypt_connection_id);
                    friendlist[i].crypt_connection_id = -1;
                    set_friend_status(i, FRIEND_CONFIRMED);
                }
                break;
            }
        }
    }
}
Exemplo n.º 15
0
//TODO: make this function not suck.
static void doFriends()
{
    /* TODO: add incoming connections and some other stuff. */
    uint32_t i;
    int len;
    uint8_t temp[MAX_DATA_SIZE];
    for (i = 0; i < numfriends; ++i) {
        if (friendlist[i].status == 1) {
            int fr = send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size);
            if (fr == 0) /* TODO: This needs to be fixed so that it sends the friend requests a couple of times in case of packet loss */
                friendlist[i].status = 2;
            else if (fr > 0)
                friendlist[i].status = 2;
        }
        if (friendlist[i].status == 2 || friendlist[i].status == 3) { /* friend is not online */
            if (friendlist[i].status == 2) {
                if (friendlist[i].friend_request_id + 10 < unix_time()) { /*I know this is hackish but it should work.*/
                    send_friendrequest(friendlist[i].client_id, friendlist[i].info, friendlist[i].info_size);
                    friendlist[i].friend_request_id = unix_time();
                }
            }
            IP_Port friendip = DHT_getfriendip(friendlist[i].client_id);
            switch (is_cryptoconnected(friendlist[i].crypt_connection_id)) {
            case 0:
                if (friendip.ip.i > 1)
                    friendlist[i].crypt_connection_id = crypto_connect(friendlist[i].client_id, friendip);
                break;
            case 3: /*  Connection is established */
                friendlist[i].status = 4;
                break;
            case 4:
                crypto_kill(friendlist[i].crypt_connection_id);
                friendlist[i].crypt_connection_id = -1;
                break;
            default:
                break;
            }
        }
        while (friendlist[i].status == 4) { /* friend is online */
            if (friendlist[i].name_sent == 0) {
                if (m_sendname(i, self_name, self_name_length))
                    friendlist[i].name_sent = 1;
            }
            if (friendlist[i].userstatus_sent == 0) {
                if (send_userstatus(i, self_userstatus, self_userstatus_len))
                    friendlist[i].userstatus_sent = 1;
            }
            len = read_cryptpacket(friendlist[i].crypt_connection_id, temp);
            if (len > 0) {
                switch (temp[0]) {
                case PACKET_ID_NICKNAME: {
                    if (len >= MAX_NAME_LENGTH + 1 || len == 1)
                        break;
                    if(friend_namechange_isset)
                        friend_namechange(i, temp + 1, len - 1);
                    memcpy(friendlist[i].name, temp + 1, len - 1);
                    friendlist[i].name[len - 2] = 0; /* make sure the NULL terminator is present. */
                    break;
                }
                case PACKET_ID_USERSTATUS: {
                    uint8_t *status = calloc(MIN(len - 1, MAX_USERSTATUS_LENGTH), 1);
                    memcpy(status, temp + 1, MIN(len - 1, MAX_USERSTATUS_LENGTH));
                    if (friend_statuschange_isset)
                        friend_statuschange(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH));
                    set_friend_userstatus(i, status, MIN(len - 1, MAX_USERSTATUS_LENGTH));
                    free(status);
                    break;
                }
                case PACKET_ID_MESSAGE: {
                    if (friend_message_isset)
                        (*friend_message)(i, temp + 1, len - 1);
                    break;
                }
                }
            } else {
                if (is_cryptoconnected(friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */
                    crypto_kill(friendlist[i].crypt_connection_id);
                    friendlist[i].crypt_connection_id = -1;
                    friendlist[i].status = 3;
                }
                break;
            }
        }
    }
}
Exemplo n.º 16
0
//TODO: make this function not suck.
void doFriends(Messenger *m)
{
    /* TODO: add incoming connections and some other stuff. */
    uint32_t i;
    int len;
    uint8_t temp[MAX_DATA_SIZE];
    uint64_t temp_time = unix_time();

    for (i = 0; i < m->numfriends; ++i) {
        if (m->friendlist[i].status == FRIEND_ADDED) {
            int fr = send_friendrequest(m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, m->friendlist[i].info,
                                        m->friendlist[i].info_size);

            if (fr >= 0) {
                set_friend_status(m, i, FRIEND_REQUESTED);
                m->friendlist[i].friendrequest_lastsent = temp_time;
            }
        }

        if (m->friendlist[i].status == FRIEND_REQUESTED
                || m->friendlist[i].status == FRIEND_CONFIRMED) { /* friend is not online */
            if (m->friendlist[i].status == FRIEND_REQUESTED) {
                /* If we didn't connect to friend after successfully sending him a friend request the request is deemed
                   unsuccessful so we set the status back to FRIEND_ADDED and try again.*/
                if (m->friendlist[i].friendrequest_lastsent + m->friendlist[i].friendrequest_timeout < temp_time) {
                    set_friend_status(m, i, FRIEND_ADDED);
                    /* Double the default timeout everytime if friendrequest is assumed to have been
                       sent unsuccessfully. */
                    m->friendlist[i].friendrequest_timeout *= 2;
                }
            }

            IP_Port friendip = DHT_getfriendip(m->friendlist[i].client_id);

            switch (is_cryptoconnected(m->friendlist[i].crypt_connection_id)) {
                case 0:
                    if (friendip.ip.i > 1)
                        m->friendlist[i].crypt_connection_id = crypto_connect(m->friendlist[i].client_id, friendip);

                    break;

                case 3: /*  Connection is established */
                    set_friend_status(m, i, FRIEND_ONLINE);
                    m->friendlist[i].name_sent = 0;
                    m->friendlist[i].userstatus_sent = 0;
                    m->friendlist[i].statusmessage_sent = 0;
                    m->friendlist[i].ping_lastrecv = temp_time;
                    break;

                case 4:
                    crypto_kill(m->friendlist[i].crypt_connection_id);
                    m->friendlist[i].crypt_connection_id = -1;
                    break;

                default:
                    break;
            }
        }

        while (m->friendlist[i].status == FRIEND_ONLINE) { /* friend is online */
            if (m->friendlist[i].name_sent == 0) {
                if (m_sendname(m, i, m->name, m->name_length))
                    m->friendlist[i].name_sent = 1;
            }

            if (m->friendlist[i].statusmessage_sent == 0) {
                if (send_statusmessage(m, i, m->statusmessage, m->statusmessage_length))
                    m->friendlist[i].statusmessage_sent = 1;
            }

            if (m->friendlist[i].userstatus_sent == 0) {
                if (send_userstatus(m, i, m->userstatus))
                    m->friendlist[i].userstatus_sent = 1;
            }

            if (m->friendlist[i].ping_lastsent + FRIEND_PING_INTERVAL < temp_time) {
                send_ping(m, i);
            }

            len = read_cryptpacket(m->friendlist[i].crypt_connection_id, temp);
            uint8_t packet_id = temp[0];
            uint8_t *data = temp + 1;
            int data_length = len - 1;

            if (len > 0) {
                switch (packet_id) {
                    case PACKET_ID_PING: {
                        m->friendlist[i].ping_lastrecv = temp_time;
                        break;
                    }

                    case PACKET_ID_NICKNAME: {
                        if (data_length >= MAX_NAME_LENGTH || data_length == 0)
                            break;

                        if (m->friend_namechange)
                            m->friend_namechange(m, i, data, data_length, m->friend_namechange_userdata);

                        memcpy(m->friendlist[i].name, data, data_length);
                        m->friendlist[i].name[data_length - 1] = 0; /* make sure the NULL terminator is present. */
                        break;
                    }

                    case PACKET_ID_STATUSMESSAGE: {
                        if (data_length == 0)
                            break;

                        uint8_t *status = calloc(MIN(data_length, MAX_STATUSMESSAGE_LENGTH), 1);
                        memcpy(status, data, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));

                        if (m->friend_statusmessagechange)
                            m->friend_statusmessagechange(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH),
                                                          m->friend_statuschange_userdata);

                        set_friend_statusmessage(m, i, status, MIN(data_length, MAX_STATUSMESSAGE_LENGTH));
                        free(status);
                        break;
                    }

                    case PACKET_ID_USERSTATUS: {
                        if (data_length != 1)
                            break;

                        USERSTATUS status = data[0];

                        if (m->friend_userstatuschange)
                            m->friend_userstatuschange(m, i, status, m->friend_userstatuschange_userdata);

                        set_friend_userstatus(m, i, status);
                        break;
                    }

                    case PACKET_ID_MESSAGE: {
                        uint8_t *message_id = data;
                        uint8_t message_id_length = 4;
                        uint8_t *message = data + message_id_length;
                        uint16_t message_length = data_length - message_id_length;

                        if (m->friendlist[i].receives_read_receipts) {
                            write_cryptpacket_id(m, i, PACKET_ID_RECEIPT, message_id, message_id_length);
                        }

                        if (m->friend_message)
                            (*m->friend_message)(m, i, message, message_length, m->friend_message_userdata);

                        break;
                    }

                    case PACKET_ID_ACTION: {
                        if (m->friend_action)
                            (*m->friend_action)(m, i, data, data_length, m->friend_action_userdata);

                        break;
                    }

                    case PACKET_ID_RECEIPT: {
                        uint32_t msgid;

                        if (data_length < sizeof(msgid))
                            break;

                        memcpy(&msgid, data, sizeof(msgid));
                        msgid = ntohl(msgid);

                        if (m->read_receipt)
                            (*m->read_receipt)(m, i, msgid, m->read_receipt_userdata);

                        break;
                    }
                }
            } else {
                if (is_cryptoconnected(m->friendlist[i].crypt_connection_id) == 4) { /* if the connection timed out, kill it */
                    crypto_kill(m->friendlist[i].crypt_connection_id);
                    m->friendlist[i].crypt_connection_id = -1;
                    set_friend_status(m, i, FRIEND_CONFIRMED);
                }

                break;
            }

            if (m->friendlist[i].ping_lastrecv + FRIEND_CONNECTION_TIMEOUT < temp_time) {
                /* if we stopped recieving ping packets kill it */
                crypto_kill(m->friendlist[i].crypt_connection_id);
                m->friendlist[i].crypt_connection_id = -1;
                set_friend_status(m, i, FRIEND_CONFIRMED);
            }
        }
    }
}
Exemplo n.º 17
0
/* Handle received packets for not yet established crypto connections. */
static void receive_crypto(Net_Crypto *c)
{
    uint32_t i;

    for (i = 0; i < c->crypto_connections_length; ++i) {
        if (c->crypto_connections[i].status == CONN_HANDSHAKE_SENT) {
            uint8_t temp_data[MAX_DATA_SIZE];
            uint8_t secret_nonce[crypto_box_NONCEBYTES];
            uint8_t public_key[crypto_box_PUBLICKEYBYTES];
            uint8_t session_key[crypto_box_PUBLICKEYBYTES];
            uint16_t len;

            if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 2) { /* Handle handshake packet. */
                len = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data);

                if (handle_cryptohandshake(c, public_key, secret_nonce, session_key, temp_data, len)) {
                    if (memcmp(public_key, c->crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) {
                        memcpy(c->crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
                        memcpy(c->crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
                        increment_nonce(c->crypto_connections[i].sent_nonce);
                        uint32_t zero = 0;
                        encrypt_precompute(c->crypto_connections[i].peersessionpublic_key,
                                           c->crypto_connections[i].sessionsecret_key,
                                           c->crypto_connections[i].shared_key);
                        c->crypto_connections[i].status =
                            CONN_ESTABLISHED; /* Connection status needs to be 3 for write_cryptpacket() to work. */
                        write_cryptpacket(c, i, ((uint8_t *)&zero), sizeof(zero));
                        c->crypto_connections[i].status = CONN_NOT_CONFIRMED; /* Set it to its proper value right after. */
                    }
                }
            } else if (id_packet(c->lossless_udp,
                                 c->crypto_connections[i].number) != -1) { // This should not happen, kill the connection if it does.
                crypto_kill(c, i);
                return;
            }
        }

        if (c->crypto_connections[i].status == CONN_NOT_CONFIRMED) {
            if (id_packet(c->lossless_udp, c->crypto_connections[i].number) == 3) {
                uint8_t temp_data[MAX_DATA_SIZE];
                uint8_t data[MAX_DATA_SIZE];
                int length = read_packet(c->lossless_udp, c->crypto_connections[i].number, temp_data);
                int len = decrypt_data(c->crypto_connections[i].peersessionpublic_key,
                                       c->crypto_connections[i].sessionsecret_key,
                                       c->crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data);
                uint32_t zero = 0;

                if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) {
                    increment_nonce(c->crypto_connections[i].recv_nonce);
                    encrypt_precompute(c->crypto_connections[i].peersessionpublic_key,
                                       c->crypto_connections[i].sessionsecret_key,
                                       c->crypto_connections[i].shared_key);
                    c->crypto_connections[i].status = CONN_ESTABLISHED;

                    /* Connection is accepted so we disable the auto kill by setting it to about 1 month from now. */
                    kill_connection_in(c->lossless_udp, c->crypto_connections[i].number, 3000000);
                } else {
                    /* This should not happen, kill the connection if it does. */
                    crypto_kill(c, i);
                    return;
                }
            } else if (id_packet(c->lossless_udp, c->crypto_connections[i].number) != -1)
                /* This should not happen, kill the connection if it does. */
                crypto_kill(c, i);

            return;
        }
    }
}