Beispiel #1
0
static tau_transaction_t
tau_transaction_new( void )
{
    tau_transaction_t tmp;
    tr_cryptoRandBuf( &tmp, sizeof( tau_transaction_t ) );
    return tmp;
}
Beispiel #2
0
char*
tr_ssha1( const void * plaintext )
{
    enum { saltval_len = 8,
           salter_len  = 64 };
    static const char * salter = "0123456789"
                                 "abcdefghijklmnopqrstuvwxyz"
                                 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                 "./";

    size_t i;
    unsigned char salt[saltval_len];
    uint8_t sha[SHA_DIGEST_LENGTH];
    char buf[2*SHA_DIGEST_LENGTH + saltval_len + 2];

    tr_cryptoRandBuf( salt, saltval_len );
    for( i=0; i<saltval_len; ++i )
        salt[i] = salter[ salt[i] % salter_len ];

    tr_sha1( sha, plaintext, strlen( plaintext ), salt, saltval_len, NULL );
    tr_sha1_to_hex( &buf[1], sha );
    memcpy( &buf[1+2*SHA_DIGEST_LENGTH], &salt, saltval_len );
    buf[1+2*SHA_DIGEST_LENGTH + saltval_len] = '\0';
    buf[0] = '{'; /* signal that this is a hash. this makes saving/restoring
                     easier */

    return tr_strdup( &buf );
}
Beispiel #3
0
static int
readYa( tr_handshake *    handshake,
        struct evbuffer * inbuf )
{
    uint8_t        ya[KEY_LEN];
    uint8_t *      walk, outbuf[KEY_LEN + PadB_MAXLEN];
    const uint8_t *myKey, *secret;
    int            len;

    dbgmsg( handshake, "in readYa... need %d, have %zu",
            KEY_LEN, evbuffer_get_length( inbuf ) );
    if( evbuffer_get_length( inbuf ) < KEY_LEN )
        return READ_LATER;

    /* read the incoming peer's public key */
    evbuffer_remove( inbuf, ya, KEY_LEN );
    secret = tr_cryptoComputeSecret( handshake->crypto, ya );
    memcpy( handshake->mySecret, secret, KEY_LEN );
    tr_sha1( handshake->myReq1, "req1", 4, secret, KEY_LEN, NULL );

    dbgmsg( handshake, "sending B->A: Diffie Hellman Yb, PadB" );
    /* send our public key to the peer */
    walk = outbuf;
    myKey = tr_cryptoGetMyPublicKey( handshake->crypto, &len );
    memcpy( walk, myKey, len );
    walk += len;
    len = tr_cryptoRandInt( PadB_MAXLEN );
    tr_cryptoRandBuf( walk, len );
    walk += len;

    setReadState( handshake, AWAITING_PAD_A );
    tr_peerIoWriteBytes( handshake->io, outbuf, walk - outbuf, FALSE );
    return READ_NOW;
}
Beispiel #4
0
/* 1 A->B: Diffie Hellman Ya, PadA */
static void
sendYa( tr_handshake * handshake )
{
    int               len;
    const uint8_t *   public_key;
    char              outbuf[ KEY_LEN + PadA_MAXLEN ], *walk=outbuf;

    /* add our public key (Ya) */
    public_key = tr_cryptoGetMyPublicKey( handshake->crypto, &len );
    assert( len == KEY_LEN );
    assert( public_key );
    memcpy( walk, public_key, len );
    walk += len;

    /* add some bullshit padding */
    len = tr_cryptoRandInt( PadA_MAXLEN );
    tr_cryptoRandBuf( walk, len );
    walk += len;

    /* send it */
    setReadState( handshake, AWAITING_YB );
    tr_peerIoWriteBytes( handshake->io, outbuf, walk - outbuf, FALSE );
}
Beispiel #5
0
int
tr_dhtInit(tr_session *ss, const tr_address * tr_addr)
{
    struct sockaddr_in sin;
    tr_benc benc;
    int rc;
    tr_bool have_id = FALSE;
    char * dat_file;
    uint8_t * nodes = NULL, * nodes6 = NULL;
    const uint8_t * raw;
    size_t len, len6;
    struct bootstrap_closure * cl;

    if( session ) /* already initialized */
        return -1;

    dht_port = tr_sessionGetPeerPort(ss);
    if(dht_port <= 0)
        return -1;

    tr_ndbg( "DHT", "Initializing DHT" );

    dht_socket = socket(PF_INET, SOCK_DGRAM, 0);
    if(dht_socket < 0)
        goto fail;

    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    memcpy(&sin.sin_addr, &tr_addr->addr.addr4, sizeof (struct in_addr));
    sin.sin_port = htons(dht_port);
    rc = bind(dht_socket, (struct sockaddr*)&sin, sizeof(sin));
    if(rc < 0)
        goto fail;

    if(tr_globalIPv6())
        rebind_ipv6(TRUE);

    if( getenv( "TR_DHT_VERBOSE" ) != NULL )
        dht_debug = stderr;

    dat_file = tr_buildPath( ss->configDir, "dht.dat", NULL );
    rc = tr_bencLoadFile( &benc, TR_FMT_BENC, dat_file );
    tr_free( dat_file );
    if(rc == 0) {
        have_id = tr_bencDictFindRaw(&benc, "id", &raw, &len);
        if( have_id && len==20 )
            memcpy( myid, raw, len );
        if( dht_socket >= 0 &&
            tr_bencDictFindRaw( &benc, "nodes", &raw, &len ) && !(len%6) ) {
                nodes = tr_memdup( raw, len );
        }
        if( dht6_socket > 0 &&
            tr_bencDictFindRaw( &benc, "nodes6", &raw, &len6 ) && !(len6%18) ) {
            nodes6 = tr_memdup( raw, len6 );
        }
        tr_bencFree( &benc );
    }

    if(nodes == NULL)
        len = 0;
    if(nodes6 == NULL)
        len6 = 0;

    if( have_id )
        tr_ninf( "DHT", "Reusing old id" );
    else {
        /* Note that DHT ids need to be distributed uniformly,
         * so it should be something truly random. */
        tr_ninf( "DHT", "Generating new id" );
        tr_cryptoRandBuf( myid, 20 );
    }

    rc = dht_init( dht_socket, dht6_socket, myid, NULL );
    if( rc < 0 )
        goto fail;

    session = ss;

    cl = tr_new( struct bootstrap_closure, 1 );
    cl->session = session;
    cl->nodes = nodes;
    cl->nodes6 = nodes6;
    cl->len = len;
    cl->len6 = len6;
    tr_threadNew( dht_bootstrap, cl );

    dht_event = event_new( session->event_base, dht_socket, EV_READ, event_callback, NULL );
    tr_timerAdd( dht_event, 0, tr_cryptoWeakRandInt( 1000000 ) );

    if( dht6_socket >= 0 )
    {
        dht6_event = event_new( session->event_base, dht6_socket, EV_READ, event_callback, NULL );
        tr_timerAdd( dht6_event, 0, tr_cryptoWeakRandInt( 1000000 ) );
    }

    tr_ndbg( "DHT", "DHT initialized" );

    return 1;

    fail:
    {
        const int save = errno;
        close(dht_socket);
        if( dht6_socket >= 0 )
            close(dht6_socket);
        dht_socket = dht6_socket = -1;
        session = NULL;
        tr_ndbg( "DHT", "DHT initialization failed (errno = %d)", save );
        errno = save;
    }

    return -1;
}
Beispiel #6
0
int
tr_dhtInit(tr_session *ss)
{
    tr_benc benc;
    int rc;
    bool have_id = false;
    char * dat_file;
    uint8_t * nodes = NULL, * nodes6 = NULL;
    const uint8_t * raw;
    size_t len, len6;
    struct bootstrap_closure * cl;

    if( session ) /* already initialized */
        return -1;

    tr_ndbg( "DHT", "Initializing DHT" );

    if( getenv( "TR_DHT_VERBOSE" ) != NULL )
        dht_debug = stderr;

    dat_file = tr_buildPath( ss->configDir, "dht.dat", NULL );
    rc = tr_bencLoadFile( &benc, TR_FMT_BENC, dat_file );
    tr_free( dat_file );
    if(rc == 0) {
        have_id = tr_bencDictFindRaw(&benc, "id", &raw, &len);
        if( have_id && len==20 )
            memcpy( myid, raw, len );
        if( ss->udp_socket >= 0 &&
            tr_bencDictFindRaw( &benc, "nodes", &raw, &len ) && !(len%6) ) {
                nodes = tr_memdup( raw, len );
        }
        if( ss->udp6_socket > 0 &&
            tr_bencDictFindRaw( &benc, "nodes6", &raw, &len6 ) && !(len6%18) ) {
            nodes6 = tr_memdup( raw, len6 );
        }
        tr_bencFree( &benc );
    }

    if(nodes == NULL)
        len = 0;
    if(nodes6 == NULL)
        len6 = 0;

    if( have_id )
        tr_ninf( "DHT", "Reusing old id" );
    else {
        /* Note that DHT ids need to be distributed uniformly,
         * so it should be something truly random. */
        tr_ninf( "DHT", "Generating new id" );
        tr_cryptoRandBuf( myid, 20 );
    }

    rc = dht_init( ss->udp_socket, ss->udp6_socket, myid, NULL );
    if( rc < 0 )
        goto fail;

    session = ss;

    cl = tr_new( struct bootstrap_closure, 1 );
    cl->session = session;
    cl->nodes = nodes;
    cl->nodes6 = nodes6;
    cl->len = len;
    cl->len6 = len6;
    tr_threadNew( dht_bootstrap, cl );

    dht_timer = evtimer_new( session->event_base, timer_callback, session );
    tr_timerAdd( dht_timer, 0, tr_cryptoWeakRandInt( 1000000 ) );

    tr_ndbg( "DHT", "DHT initialized" );

    return 1;

 fail:
    tr_ndbg( "DHT", "DHT initialization failed (errno = %d)", errno );
    session = NULL;
    return -1;
}