예제 #1
0
static int
readCryptoSelect( tr_handshake *    handshake,
                  struct evbuffer * inbuf )
{
    uint32_t     crypto_select;
    uint16_t     pad_d_len;
    const size_t needlen = sizeof( uint32_t ) + sizeof( uint16_t );

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

    tr_peerIoReadUint32( handshake->io, inbuf, &crypto_select );
    handshake->crypto_select = crypto_select;
    dbgmsg( handshake, "crypto select is %d", (int)crypto_select );
    if( !( crypto_select & getCryptoProvide( handshake ) ) )
    {
        dbgmsg( handshake,
                "peer selected an encryption option we didn't provide" );
        return tr_handshakeDone( handshake, FALSE );
    }

    tr_peerIoReadUint16( handshake->io, inbuf, &pad_d_len );
    dbgmsg( handshake, "pad_d_len is %d", (int)pad_d_len );

    if( pad_d_len > 512 )
    {
        dbgmsg( handshake, "encryption handshake: pad_d_len is too long" );
        return tr_handshakeDone( handshake, FALSE );
    }

    handshake->pad_d_len = pad_d_len;

    setState( handshake, AWAITING_PAD_D );
    return READ_NOW;
}
예제 #2
0
static int
readPadC( tr_handshake *    handshake,
          struct evbuffer * inbuf )
{
    uint16_t     ia_len;
    const size_t needlen = handshake->pad_c_len + sizeof( uint16_t );

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

    evbuffer_drain( inbuf, handshake->pad_c_len );

    tr_peerIoReadUint16( handshake->io, inbuf, &ia_len );
    dbgmsg( handshake, "ia_len is %d", (int)ia_len );
    handshake->ia_len = ia_len;
    setState( handshake, AWAITING_IA );
    return READ_NOW;
}
예제 #3
0
static int
readPadC (tr_handshake    * handshake,
          struct evbuffer * inbuf)
{
  char * padc;
  uint16_t ia_len;
  const size_t needlen = handshake->pad_c_len + sizeof (uint16_t);

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

  /* read the throwaway padc */
  padc = tr_new (char, handshake->pad_c_len);
  tr_peerIoReadBytes (handshake->io, inbuf, padc, handshake->pad_c_len);
  tr_free (padc);

  /* read ia_len */
  tr_peerIoReadUint16 (handshake->io, inbuf, &ia_len);
  dbgmsg (handshake, "ia_len is %d", (int)ia_len);
  handshake->ia_len = ia_len;
  setState (handshake, AWAITING_IA);
  return READ_NOW;
}
예제 #4
0
static int
readCryptoProvide( tr_handshake *    handshake,
                   struct evbuffer * inbuf )
{
    /* HASH('req2', SKEY) xor HASH('req3', S), ENCRYPT(VC, crypto_provide,
      len(PadC)) */

    int          i;
    uint8_t      vc_in[VC_LENGTH];
    uint8_t      req2[SHA_DIGEST_LENGTH];
    uint8_t      req3[SHA_DIGEST_LENGTH];
    uint8_t      obfuscatedTorrentHash[SHA_DIGEST_LENGTH];
    uint16_t     padc_len = 0;
    uint32_t     crypto_provide = 0;
    const size_t needlen = SHA_DIGEST_LENGTH /* HASH('req1',s) */
                           + SHA_DIGEST_LENGTH /* HASH('req2', SKEY) xor
                                                 HASH('req3', S) */
                           + VC_LENGTH
                           + sizeof( crypto_provide )
                           + sizeof( padc_len );
    tr_torrent * tor = NULL;

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

    /* TODO: confirm they sent HASH('req1',S) here? */
    evbuffer_drain( inbuf, SHA_DIGEST_LENGTH );

    /* This next piece is HASH('req2', SKEY) xor HASH('req3', S) ...
     * we can get the first half of that (the obufscatedTorrentHash)
     * by building the latter and xor'ing it with what the peer sent us */
    dbgmsg( handshake, "reading obfuscated torrent hash..." );
    evbuffer_remove( inbuf, req2, SHA_DIGEST_LENGTH );
    tr_sha1( req3, "req3", 4, handshake->mySecret, KEY_LEN, NULL );
    for( i = 0; i < SHA_DIGEST_LENGTH; ++i )
        obfuscatedTorrentHash[i] = req2[i] ^ req3[i];
    if(( tor = tr_torrentFindFromObfuscatedHash( handshake->session, obfuscatedTorrentHash )))
    {
        const tr_bool clientIsSeed = tr_torrentIsSeed( tor );
        const tr_bool peerIsSeed = tr_peerMgrPeerIsSeed( tor, tr_peerIoGetAddress( handshake->io, NULL ) );
        dbgmsg( handshake, "got INCOMING connection's encrypted handshake for torrent [%s]",
                tr_torrentName( tor ) );
        tr_peerIoSetTorrentHash( handshake->io, tor->info.hash );

        if( clientIsSeed && peerIsSeed )
        {
            dbgmsg( handshake, "another seed tried to reconnect to us!" );
            return tr_handshakeDone( handshake, FALSE );
        }
    }
    else
    {
        dbgmsg( handshake, "can't find that torrent..." );
        return tr_handshakeDone( handshake, FALSE );
    }

    /* next part: ENCRYPT(VC, crypto_provide, len(PadC), */

    tr_cryptoDecryptInit( handshake->crypto );

    tr_peerIoReadBytes( handshake->io, inbuf, vc_in, VC_LENGTH );

    tr_peerIoReadUint32( handshake->io, inbuf, &crypto_provide );
    handshake->crypto_provide = crypto_provide;
    dbgmsg( handshake, "crypto_provide is %d", (int)crypto_provide );

    tr_peerIoReadUint16( handshake->io, inbuf, &padc_len );
    dbgmsg( handshake, "padc is %d", (int)padc_len );
    handshake->pad_c_len = padc_len;
    setState( handshake, AWAITING_PAD_C );
    return READ_NOW;
}