Esempio n. 1
0
static int
readVC( tr_handshake *    handshake,
        struct evbuffer * inbuf )
{
    const uint8_t key[VC_LENGTH] = { 0, 0, 0, 0, 0, 0, 0, 0 };
    const int     key_len = VC_LENGTH;
    uint8_t       tmp[VC_LENGTH];

    /* note: this works w/o having to `unwind' the buffer if
     * we read too much, but it is pretty brute-force.
     * it would be nice to make this cleaner. */
    for( ; ; )
    {
        if( evbuffer_get_length( inbuf ) < VC_LENGTH )
        {
            dbgmsg( handshake, "not enough bytes... returning read_more" );
            return READ_LATER;
        }

        memcpy( tmp, evbuffer_pullup( inbuf, key_len ), key_len );
        tr_cryptoDecryptInit( handshake->crypto );
        tr_cryptoDecrypt( handshake->crypto, key_len, tmp, tmp );
        if( !memcmp( tmp, key, key_len ) )
            break;

        evbuffer_drain( inbuf, 1 );
    }

    dbgmsg( handshake, "got it!" );
    evbuffer_drain( inbuf, key_len );
    setState( handshake, AWAITING_CRYPTO_SELECT );
    return READ_NOW;
}
Esempio n. 2
0
void
tr_peerIoReadBytes( tr_peerIo       * io,
                    struct evbuffer * inbuf,
                    void            * bytes,
                    size_t            byteCount )
{
    assert( tr_isPeerIo( io ) );
    /* FIXME(libevent2): use evbuffer_get_length() */
    assert( EVBUFFER_LENGTH( inbuf ) >= byteCount );

    switch( io->encryptionMode )
    {
        case PEER_ENCRYPTION_NONE:
            evbuffer_remove( inbuf, bytes, byteCount );
            break;

        case PEER_ENCRYPTION_RC4:
            /* FIXME(libevent2): loop through calls to evbuffer_get_contiguous_space() + evbuffer_drain() */
            tr_cryptoDecrypt( io->crypto, byteCount, EVBUFFER_DATA(inbuf), bytes );
            evbuffer_drain(inbuf, byteCount );
            break;

        default:
            assert( 0 );
    }
}
Esempio n. 3
0
static int
test_encrypt_decrypt (void)
{
  tr_crypto a, b;
  uint8_t hash[SHA_DIGEST_LENGTH];
  const char test1[] = { "test1" };
  char buf11[sizeof (test1)], buf12[sizeof (test1)];
  const char test2[] = { "@#)C$@)#(*%bvkdjfhwbc039bc4603756VB3)" };
  char buf21[sizeof (test2)], buf22[sizeof (test2)];
  int i;

  for (i = 0; i < SHA_DIGEST_LENGTH; ++i)
    hash[i] = i;

  tr_cryptoConstruct (&a, hash, false);
  tr_cryptoConstruct (&b, hash, true);
  tr_cryptoComputeSecret (&a, tr_cryptoGetMyPublicKey (&b, &i));
  tr_cryptoComputeSecret (&b, tr_cryptoGetMyPublicKey (&a, &i));

  tr_cryptoEncryptInit (&a);
  tr_cryptoEncrypt (&a, sizeof (test1), test1, buf11);
  tr_cryptoDecryptInit (&b);
  tr_cryptoDecrypt (&b, sizeof (test1), buf11, buf12);
  check_streq (test1, buf12);

  tr_cryptoEncryptInit (&b);
  tr_cryptoEncrypt (&b, sizeof (test2), test2, buf21);
  tr_cryptoDecryptInit (&a);
  tr_cryptoDecrypt (&a, sizeof (test2), buf21, buf22);
  check_streq (test2, buf22);

  tr_cryptoDestruct (&b);
  tr_cryptoDestruct (&a);

  return 0;
}
Esempio n. 4
0
static int
readHandshake( tr_handshake *    handshake,
               struct evbuffer * inbuf )
{
    uint8_t   pstrlen;
    uint8_t * pstr;
    uint8_t   reserved[HANDSHAKE_FLAGS_LEN];
    uint8_t   hash[SHA_DIGEST_LENGTH];

    dbgmsg( handshake, "payload: need %d, got %zu",
            INCOMING_HANDSHAKE_LEN, evbuffer_get_length( inbuf ) );

    if( evbuffer_get_length( inbuf ) < INCOMING_HANDSHAKE_LEN )
        return READ_LATER;

    handshake->haveReadAnythingFromPeer = TRUE;

    pstrlen = evbuffer_pullup( inbuf, 1 )[0]; /* peek, don't read. We may be
                                                 handing inbuf to AWAITING_YA */

    if( pstrlen == 19 ) /* unencrypted */
    {
        tr_peerIoSetEncryption( handshake->io, PEER_ENCRYPTION_NONE );

        if( handshake->encryptionMode == TR_ENCRYPTION_REQUIRED )
        {
            dbgmsg( handshake,
                    "peer is unencrypted, and we're disallowing that" );
            return tr_handshakeDone( handshake, FALSE );
        }
    }
    else /* encrypted or corrupt */
    {
        tr_peerIoSetEncryption( handshake->io, PEER_ENCRYPTION_RC4 );

        if( tr_peerIoIsIncoming( handshake->io ) )
        {
            dbgmsg( handshake,
                    "I think peer is sending us an encrypted handshake..." );
            setState( handshake, AWAITING_YA );
            return READ_NOW;
        }
        tr_cryptoDecrypt( handshake->crypto, 1, &pstrlen, &pstrlen );

        if( pstrlen != 19 )
        {
            dbgmsg( handshake,
                    "I think peer has sent us a corrupt handshake..." );
            return tr_handshakeDone( handshake, FALSE );
        }
    }

    evbuffer_drain( inbuf, 1 );

    /* pstr (BitTorrent) */
    pstr = tr_new( uint8_t, pstrlen + 1 );
    tr_peerIoReadBytes( handshake->io, inbuf, pstr, pstrlen );
    pstr[pstrlen] = '\0';
    if( strcmp( (char*)pstr, "BitTorrent protocol" ) )
    {
        tr_free( pstr );
        return tr_handshakeDone( handshake, FALSE );
    }
    tr_free( pstr );

    /* reserved bytes */
    tr_peerIoReadBytes( handshake->io, inbuf, reserved, sizeof( reserved ) );

    /**
    *** Extensions
    **/

    tr_peerIoEnableLTEP( handshake->io, HANDSHAKE_HAS_LTEP( reserved ) );

    tr_peerIoEnableFEXT( handshake->io, HANDSHAKE_HAS_FASTEXT( reserved ) );

    tr_peerIoEnableDHT( handshake->io, HANDSHAKE_HAS_DHT( reserved ) );

    /* torrent hash */
    tr_peerIoReadBytes( handshake->io, inbuf, hash, sizeof( hash ) );
    if( tr_peerIoIsIncoming( handshake->io ) )
    {
        if( !tr_torrentExists( handshake->session, hash ) )
        {
            dbgmsg( handshake, "peer is trying to connect to us for a torrent we don't have." );
            return tr_handshakeDone( handshake, FALSE );
        }
        else
        {
            assert( !tr_peerIoHasTorrentHash( handshake->io ) );
            tr_peerIoSetTorrentHash( handshake->io, hash );
        }
    }
    else /* outgoing */
    {
        assert( tr_peerIoHasTorrentHash( handshake->io ) );
        if( memcmp( hash, tr_peerIoGetTorrentHash( handshake->io ),
                    SHA_DIGEST_LENGTH ) )
        {
            dbgmsg( handshake, "peer returned the wrong hash. wtf?" );
            return tr_handshakeDone( handshake, FALSE );
        }
    }

    /**
    ***  If it's an incoming message, we need to send a response handshake
    **/

    if( !handshake->haveSentBitTorrentHandshake )
    {
        uint8_t msg[HANDSHAKE_SIZE];
        buildHandshakeMessage( handshake, msg );
        tr_peerIoWriteBytes( handshake->io, msg, sizeof( msg ), FALSE );
        handshake->haveSentBitTorrentHandshake = 1;
    }

    setReadState( handshake, AWAITING_PEER_ID );
    return READ_NOW;
}