source: branches/encryption/libtransmission/handshake.c @ 2985

Last change on this file since 2985 was 2985, checked in by charles, 15 years ago

work on incoming connections, and better deciding of which pieces to request first.

  • Property svn:keywords set to Date Rev Author Id
File size: 27.0 KB
Line 
1/*
2 * This file Copyright (C) 2007 Charles Kerr <charles@rebelbase.com>
3 *
4 * This file is licensed by the GPL version 2.  Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: handshake.c 2985 2007-09-07 20:55:38Z charles $
11 */
12
13#include <assert.h>
14#include <errno.h>
15#include <inttypes.h>
16#include <limits.h> /* UCHAR_MAX */
17#include <string.h>
18#include <stdio.h>
19#include <arpa/inet.h>
20
21#include <sys/types.h> /* event.h needs this */
22#include <event.h>
23
24#include "transmission.h"
25#include "bencode.h"
26#include "crypto.h"
27#include "handshake.h"
28#include "peer-io.h"
29#include "utils.h"
30
31/* enable LibTransmission extension protocol */
32#define ENABLE_LTEP
33
34/* enable Azureus messaging protocol */
35//#define ENABLE_AZMP
36
37/***
38****
39***/
40
41#define HANDSHAKE_NAME          "\023BitTorrent protocol"
42#define HANDSHAKE_NAME_LEN      20
43#define HANDSHAKE_FLAGS_LEN     8
44#define HANDSHAKE_SIZE          68
45
46#ifdef ENABLE_LTEP
47#define HANDSHAKE_HAS_EXTMSGS( bits ) ( (bits)[5] & 0x10 )
48#define HANDSHAKE_SET_EXTMSGS( bits ) ( (bits)[5] |= 0x10 )
49#else
50#define HANDSHAKE_HAS_EXTMSGS( bits ) ( 0 )
51#define HANDSHAKE_SET_EXTMSGS( bits ) ( (void)0 )
52#endif
53
54#ifdef ENABLE_AZMP
55#define HANDSHAKE_HAS_AZPROTO( bits ) ( (bits)[0] & 0x80 )
56#define HANDSHAKE_SET_AZPROTO( bits ) ( (bits)[0] |= 0x80 )
57#else
58#define HANDSHAKE_HAS_AZPROTO( bits ) ( 0 )
59#define HANDSHAKE_SET_AZPROTO( bits ) ( (void)0 )
60#endif
61
62/* http://www.azureuswiki.com/index.php/Extension_negotiation_protocol
63   these macros are to be used if both extended messaging and the
64   azureus protocol is supported, they indicate which protocol is preferred */
65#define HANDSHAKE_GET_EXTPREF( reserved )      ( (reserved)[5] & 0x03 )
66#define HANDSHAKE_SET_EXTPREF( reserved, val ) ( (reserved)[5] |= 0x03 & (val) )
67#define HANDSHAKE_EXTPREF_LTEP_FORCE   ( 0x0 )
68#define HANDSHAKE_EXTPREF_LTEP_PREFER  ( 0x1 )
69#define HANDSHAKE_EXTPREF_AZMP_PREFER  ( 0x2 )
70#define HANDSHAKE_EXTPREF_AZMP_FORCE   ( 0x3 )
71
72extern const char* getPeerId( void ) ;
73
74#define KEY_LEN 96
75#define PRIME_LEN 96
76#define VC_LENGTH 8
77
78
79typedef struct tr_handshake
80{
81    tr_peerIo * io;
82    tr_crypto * crypto;
83    struct tr_handle * handle;
84    uint8_t myPublicKey[96];
85    uint8_t mySecret[96];
86    uint8_t state;
87    uint8_t encryptionPreference;
88    uint16_t pad_c_len;
89    uint16_t pad_d_len;
90    int ia_len;
91    int crypto_select;
92    uint8_t myReq1[SHA_DIGEST_LENGTH];
93    handshakeDoneCB doneCB;
94    void * doneUserData;
95}
96tr_handshake;
97
98static void
99fireDoneCB( tr_handshake * handshake, int isConnected );
100
101/**
102***
103**/
104
105enum /*ccc*/
106{
107    /* incoming */
108    AWAITING_HANDSHAKE,
109    AWAITING_YA,
110    AWAITING_PAD_A,
111    AWAITING_CRYPTO_PROVIDE,
112    AWAITING_PAD_C,
113    AWAITING_IA,
114
115    /* outgoing */
116    AWAITING_YB,
117    AWAITING_VC,
118    AWAITING_CRYPTO_SELECT,
119    AWAITING_PAD_D,
120};
121
122/**
123***
124**/
125
126static const char* getStateName( short state )
127{
128    const char * str = "f00!";
129    switch( state ) {
130        case AWAITING_HANDSHAKE:      str = "awaiting handshake"; break;
131        case AWAITING_YA:             str = "awaiting ya"; break;
132        //case SENDING_YB:              str = "sending yb"; break;
133        case AWAITING_PAD_A:          str = "awaiting pad a"; break;
134        case AWAITING_CRYPTO_PROVIDE: str = "awaiting crypto_provide"; break;
135        case AWAITING_PAD_C:          str = "awaiting pad c"; break;
136        case AWAITING_IA:             str = "awaiting ia"; break;
137        //case SENDING_YA:              str = "sending ya"; break;
138        case AWAITING_YB:             str = "awaiting yb"; break;
139        //case SENDING_CRYPTO_PROVIDE:  str = "sending crypto provide"; break;
140        case AWAITING_VC:             str = "awaiting vc"; break;
141        case AWAITING_CRYPTO_SELECT:  str = "awaiting crypto select"; break;
142        case AWAITING_PAD_D:          str = "awaiting pad d"; break;
143        //case SENDING_PLAINTEXT_HANDSHAKE: str = "sending plaintext handshake"; break;
144    }
145    return str;
146}
147
148static void
149setState( tr_handshake * handshake, short state )
150{
151    fprintf( stderr, "handshake %p: setting to state [%s]\n", handshake, getStateName(state) );
152    handshake->state = state;
153}
154
155static void
156setReadState( tr_handshake * handshake, int state )
157{
158    setState( handshake, state );
159    //tr_peerIoSetIOMode( handshake->io, EV_READ, EV_WRITE );
160}
161
162static void
163sendPublicKey( tr_handshake * handshake )
164{
165    int i;
166    int len;
167    const uint8_t * public_key;
168    struct evbuffer * outbuf = evbuffer_new( );
169    uint8_t pad[512];
170
171    /* add our public key (Ya) */
172    public_key = tr_cryptoGetMyPublicKey( handshake->crypto, &len );
173    assert( len == KEY_LEN );
174    assert( public_key != NULL );
175    evbuffer_add( outbuf, public_key, len );
176
177    /* add some bullshit padding */
178    len = tr_rand( 512 );
179    for( i=0; i<len; ++i )
180        pad[i] = tr_rand( UCHAR_MAX );
181    evbuffer_add( outbuf, pad, len );
182
183    /* send it */
184    setReadState( handshake, AWAITING_YB );
185    //setState( handshake, SENDING_YA );
186    tr_peerIoWriteBuf( handshake->io, outbuf );
187
188    /* cleanup */
189    evbuffer_free( outbuf );
190}
191
192static void
193buildHandshakeMessage( tr_handshake * handshake, uint8_t * buf )
194{
195    uint8_t *walk = buf;
196    const uint8_t * torrentHash = tr_cryptoGetTorrentHash( handshake->crypto );
197
198    memcpy( walk, HANDSHAKE_NAME, HANDSHAKE_NAME_LEN );
199    walk += HANDSHAKE_NAME_LEN;
200    memset( walk, 0, HANDSHAKE_FLAGS_LEN );
201    HANDSHAKE_SET_EXTMSGS( walk );
202    HANDSHAKE_SET_AZPROTO( walk );
203    HANDSHAKE_SET_EXTPREF( walk, HANDSHAKE_EXTPREF_LTEP_PREFER );
204    walk += HANDSHAKE_FLAGS_LEN;
205    memcpy( walk, torrentHash, SHA_DIGEST_LENGTH );
206    walk += SHA_DIGEST_LENGTH;
207    memcpy( walk, getPeerId(), TR_ID_LEN );
208    walk += TR_ID_LEN;
209    assert( walk-buf == HANDSHAKE_SIZE );
210}
211
212static void
213sendPlaintextHandshake( tr_handshake * handshake )
214{
215    uint8_t buf[HANDSHAKE_SIZE];
216    buildHandshakeMessage( handshake, buf );
217
218    setReadState( handshake, AWAITING_HANDSHAKE );
219    tr_peerIoWrite( handshake->io, buf, HANDSHAKE_SIZE );
220}
221
222static void
223sendHandshake( tr_handshake * handshake )
224{
225    if( ( handshake->encryptionPreference == HANDSHAKE_ENCRYPTION_PREFERRED ) ||
226        ( handshake->encryptionPreference == HANDSHAKE_ENCRYPTION_REQUIRED ) )
227    {
228        sendPublicKey( handshake );
229    }
230    else
231    {
232        sendPlaintextHandshake( handshake );
233    }
234}
235
236static void
237sendLtepHandshake( tr_handshake * handshake )
238{
239    benc_val_t val, *m;
240    char * buf;
241    int len;
242    const char * v = TR_NAME " " USERAGENT_PREFIX;
243    const int port = tr_getPublicPort( handshake->handle );
244    struct evbuffer * outbuf = evbuffer_new( );
245    uint32_t msglen;
246    const uint8_t tr_msgid = 20; /* ltep extension id */
247    const uint8_t ltep_msgid = 0; /* handshake id */
248
249    tr_bencInit( &val, TYPE_DICT );
250    tr_bencDictReserve( &val, 3 );
251    m  = tr_bencDictAdd( &val, "m" );
252    tr_bencInit( m, TYPE_DICT );
253    tr_bencDictReserve( m, 1 );
254    tr_bencInitInt( tr_bencDictAdd( m, "ut_pex" ), 1 );
255    if( port > 0 )
256        tr_bencInitInt( tr_bencDictAdd( &val, "p" ), port );
257    tr_bencInitStr( tr_bencDictAdd( &val, "v" ), v, 0, 1 );
258
259    fprintf( stderr, "handshake %p: sending ltep handshake...\n", handshake );
260    buf = tr_bencSaveMalloc( &val,  &len );
261    tr_bencPrint( &val );
262
263    msglen = sizeof(tr_msgid) + sizeof(ltep_msgid) + len;
264    tr_peerIoWriteUint32( handshake->io, outbuf, msglen );
265    tr_peerIoWriteBytes ( handshake->io, outbuf, &tr_msgid, 1 );
266    tr_peerIoWriteBytes ( handshake->io, outbuf, &ltep_msgid, 1 );
267    tr_peerIoWriteBytes ( handshake->io, outbuf, buf, len );
268   
269    tr_peerIoWriteBuf( handshake->io, outbuf );
270    fireDoneCB( handshake, TRUE );
271 
272    /* cleanup */ 
273    tr_bencFree( &val );
274    tr_free( buf ); 
275    evbuffer_free( outbuf );
276}
277
278
279/**
280***
281**/
282
283static int
284readYa( tr_handshake * handshake, struct evbuffer  * inbuf )
285{
286    uint8_t ya[KEY_LEN];
287    uint8_t *walk, outbuf[KEY_LEN + 512];
288    const uint8_t *myKey, *secret;
289    int len;
290
291    if( EVBUFFER_LENGTH( inbuf ) < KEY_LEN )
292        return READ_MORE;
293
294    /* read the incoming peer's public key */
295    evbuffer_remove( inbuf, ya, KEY_LEN );
296    secret = tr_cryptoComputeSecret( handshake->crypto, ya );
297    memcpy( handshake->mySecret, secret, KEY_LEN );
298    tr_sha1( handshake->myReq1, "req1", 4, secret, KEY_LEN, NULL );
299
300    /* send our public key to the peer */
301    walk = outbuf;
302    myKey = tr_cryptoGetMyPublicKey( handshake->crypto, &len );
303    memcpy( walk, myKey, len );
304    len = tr_rand( 512 );
305    while( len-- )
306        *walk++ = tr_rand( UCHAR_MAX );
307
308    setReadState( handshake, AWAITING_PAD_A );
309    tr_peerIoWrite( handshake->io, outbuf, walk-outbuf );
310
311    return READ_DONE;
312}
313
314static int
315readPadA( tr_handshake * handshake, struct evbuffer * inbuf )
316{
317    uint8_t * pch;
318
319    /**
320    *** Resynchronizing on HASH('req1',S)
321    **/
322
323    pch = memchr( EVBUFFER_DATA(inbuf),
324                  handshake->myReq1[0],
325                  EVBUFFER_LENGTH(inbuf) );
326    if( pch == NULL ) {
327        evbuffer_drain( inbuf, EVBUFFER_LENGTH(inbuf) );
328        return READ_MORE;
329    }
330    evbuffer_drain( inbuf, pch-EVBUFFER_DATA(inbuf) );
331    if( EVBUFFER_LENGTH(inbuf) < SHA_DIGEST_LENGTH )
332        return READ_MORE;
333    if( memcmp( EVBUFFER_DATA(inbuf), handshake->myReq1, SHA_DIGEST_LENGTH ) ) {
334        evbuffer_drain( inbuf, 1 );
335        return READ_AGAIN;
336    }
337
338    setState( handshake, AWAITING_CRYPTO_PROVIDE );
339    return READ_AGAIN;
340}
341
342static int
343readCryptoProvide( tr_handshake * handshake, struct evbuffer * inbuf )
344{
345    /* HASH('req2', SKEY) xor HASH('req3', S), ENCRYPT(VC, crypto_provide, len(PadC)) */
346
347    int i;
348    uint8_t vc_in[VC_LENGTH];
349    uint8_t req2[SHA_DIGEST_LENGTH];
350    uint8_t req3[SHA_DIGEST_LENGTH];
351    uint8_t obfuscatedTorrentHash[SHA_DIGEST_LENGTH];
352    uint16_t padc_len = 0;
353    uint32_t crypto_provide = 0;
354    const size_t needlen = SHA_DIGEST_LENGTH + VC_LENGTH + sizeof(crypto_provide) + sizeof(padc_len);
355    tr_torrent * tor = NULL;
356
357    if( EVBUFFER_LENGTH(inbuf) < needlen )
358        return READ_MORE;
359
360    /* TODO: confirm they sent HASH('req1',S) here? */
361    evbuffer_drain( inbuf, SHA_DIGEST_LENGTH );
362
363    /* This next piece is HASH('req2', SKEY) xor HASH('req3', S) ...
364     * we can get the first half of that (the obufscatedTorrentHash)
365     * by building the latter and xor'ing it with what the peer sent us */
366    fprintf( stderr, "reading obfuscated torrent hash...\n" );
367    evbuffer_remove( inbuf, req2, SHA_DIGEST_LENGTH );
368    tr_sha1( req3, "req3", 4, handshake->mySecret, KEY_LEN, NULL );
369    for( i=0; i<SHA_DIGEST_LENGTH; ++i )
370        obfuscatedTorrentHash[i] = req2[i] ^ req3[i];
371    tor = tr_torrentFindFromObfuscatedHash( handshake->handle, obfuscatedTorrentHash );
372    assert( tor != NULL );
373    fprintf( stderr, "found the torrent; it's [%s]\n", tor->info.name );
374    tr_peerIoSetTorrentHash( handshake->io, tor->info.hash );
375
376    /* next part: ENCRYPT(VC, crypto_provide, len(PadC), */
377
378    tr_cryptoDecryptInit( handshake->crypto );
379
380    tr_peerIoReadBytes( handshake->io, inbuf, vc_in, VC_LENGTH );
381
382    tr_peerIoReadUint32( handshake->io, inbuf, &crypto_provide );
383    fprintf( stderr, "crypto_provide is %d\n", (int)crypto_provide );
384
385    tr_peerIoReadUint16( handshake->io, inbuf, &padc_len );
386    fprintf( stderr, "padc is %d\n", (int)padc_len );
387    handshake->pad_c_len = padc_len;
388    setState( handshake, AWAITING_PAD_C );
389    return READ_AGAIN;
390}
391
392static int
393readPadC( tr_handshake * handshake, struct evbuffer * inbuf )
394{
395    uint16_t ia_len;
396    const size_t needlen = handshake->pad_c_len + sizeof(uint16_t);
397
398    if( EVBUFFER_LENGTH(inbuf) < needlen )
399        return READ_MORE;
400
401    evbuffer_drain( inbuf, needlen );
402
403    tr_peerIoReadUint16( handshake->io, inbuf, &ia_len );
404    fprintf( stderr, "ia_len is %d\n", (int)ia_len );
405    handshake->ia_len = ia_len;
406    setState( handshake, AWAITING_IA );
407    return READ_AGAIN;
408}
409
410static int
411readIA( tr_handshake * handshake, struct evbuffer * inbuf )
412{
413    const size_t needlen = handshake->ia_len;
414    uint8_t * ia;
415
416    if( EVBUFFER_LENGTH(inbuf) < needlen )
417        return READ_MORE;
418
419    ia = tr_new( uint8_t, handshake->ia_len );
420    tr_peerIoReadBytes( handshake->io, inbuf, ia, handshake->ia_len );
421    fprintf( stderr, "got their payload ia: [%*.*s]\n", (int)needlen, (int)needlen, ia );
422
423    handshake->state = -1;
424    assert( 0 && "asdf" );
425}
426
427/**
428***
429**/
430
431static int
432readYb( tr_handshake * handshake, struct evbuffer * inbuf )
433{
434    int isEncrypted;
435    const uint8_t * secret;
436    uint8_t yb[KEY_LEN];
437    struct evbuffer * outbuf;
438    size_t needlen = HANDSHAKE_NAME_LEN;
439
440    if( EVBUFFER_LENGTH(inbuf) < needlen )
441        return READ_MORE;
442fprintf( stderr, "%*.*s\n", HANDSHAKE_NAME_LEN, HANDSHAKE_NAME_LEN, EVBUFFER_DATA(inbuf) );
443
444    isEncrypted = memcmp( EVBUFFER_DATA(inbuf), HANDSHAKE_NAME, HANDSHAKE_NAME_LEN );
445    if( isEncrypted ) {
446        needlen = KEY_LEN;
447        if( EVBUFFER_LENGTH(inbuf) < needlen )
448            return READ_MORE;
449    }
450
451    fprintf( stderr, "got a %s handshake\n", (isEncrypted ? "encrypted" : "plaintext") );
452    tr_peerIoSetEncryption( handshake->io, isEncrypted
453        ? PEER_ENCRYPTION_RC4
454        : PEER_ENCRYPTION_PLAINTEXT );
455    if( !isEncrypted ) {
456        setState( handshake, AWAITING_HANDSHAKE );
457        return READ_AGAIN;
458    }
459
460    /* compute the secret */
461    evbuffer_remove( inbuf, yb, KEY_LEN );
462    secret = tr_cryptoComputeSecret( handshake->crypto, yb );
463    memcpy( handshake->mySecret, secret, KEY_LEN );
464
465    /* now send these: HASH('req1', S), HASH('req2', SKEY) xor HASH('req3', S),
466     * ENCRYPT(VC, crypto_provide, len(PadC), PadC, len(IA)), ENCRYPT(IA) */
467    outbuf = evbuffer_new( );
468
469    /* HASH('req1', S) */
470    {
471        uint8_t req1[SHA_DIGEST_LENGTH];
472        tr_sha1( req1, "req1", 4, secret, KEY_LEN, NULL );
473        evbuffer_add( outbuf, req1, SHA_DIGEST_LENGTH );
474    }
475
476    /* HASH('req2', SKEY) xor HASH('req3', S) */
477    {
478        int i;
479        uint8_t req2[SHA_DIGEST_LENGTH];
480        uint8_t req3[SHA_DIGEST_LENGTH];
481        uint8_t buf[SHA_DIGEST_LENGTH];
482        tr_sha1( req2, "req2", 4, tr_cryptoGetTorrentHash(handshake->crypto), SHA_DIGEST_LENGTH, NULL );
483        tr_sha1( req3, "req3", 4, secret, KEY_LEN, NULL );
484        for( i=0; i<SHA_DIGEST_LENGTH; ++i )
485            buf[i] = req2[i] ^ req3[i];
486        evbuffer_add( outbuf, buf, SHA_DIGEST_LENGTH );
487    }
488     
489    /* ENCRYPT(VC, crypto_provide, len(PadC), PadC */
490    {
491        uint8_t vc[VC_LENGTH] = { 0, 0, 0, 0, 0, 0, 0, 0 };
492        uint8_t pad[512];
493        uint16_t i, len;
494        uint32_t crypto_provide;
495
496        tr_cryptoEncryptInit( handshake->crypto );
497       
498        /* vc */ 
499        tr_cryptoEncrypt( handshake->crypto, VC_LENGTH, vc, vc );
500        evbuffer_add( outbuf, vc, VC_LENGTH );
501
502        /* crypto_provide */
503        crypto_provide = 0;
504        if( handshake->encryptionPreference != HANDSHAKE_PLAINTEXT_REQUIRED )
505            crypto_provide |= (1<<0);
506        if( handshake->encryptionPreference != HANDSHAKE_ENCRYPTION_REQUIRED )
507            crypto_provide |= (1<<1);
508        assert( 1<=crypto_provide && crypto_provide<=3 );
509
510        crypto_provide = htonl( crypto_provide );
511        tr_cryptoEncrypt( handshake->crypto, sizeof(crypto_provide), &crypto_provide, &crypto_provide );
512        evbuffer_add( outbuf, &crypto_provide, sizeof(crypto_provide) );
513
514        /* len(padc) */
515        i = len = tr_rand( 512 );
516        i = htons( i );
517        tr_cryptoEncrypt( handshake->crypto, sizeof(i), &i, &i );
518        evbuffer_add( outbuf, &i, sizeof(i) );
519
520        /* padc */
521        for( i=0; i<len; ++i ) pad[i] = tr_rand( UCHAR_MAX );
522        tr_cryptoEncrypt( handshake->crypto, len, pad, pad );
523        evbuffer_add( outbuf, pad, len );
524    }
525
526    /* ENCRYPT len(IA)), ENCRYPT(IA) */
527    {
528        uint16_t i;
529        uint8_t msg[HANDSHAKE_SIZE];
530        buildHandshakeMessage( handshake, msg );
531
532        i = htons( HANDSHAKE_SIZE );
533        tr_cryptoEncrypt( handshake->crypto, sizeof(uint16_t), &i, &i );
534        evbuffer_add( outbuf, &i, sizeof(uint16_t) );
535
536        tr_cryptoEncrypt( handshake->crypto, HANDSHAKE_SIZE, msg, msg );
537        evbuffer_add( outbuf, msg, HANDSHAKE_SIZE );
538    }
539
540    /* send it */
541    tr_cryptoDecryptInit( handshake->crypto );
542    setReadState( handshake, AWAITING_VC );
543    tr_peerIoWriteBuf( handshake->io, outbuf );
544
545    /* cleanup */
546    evbuffer_free( outbuf );
547    return READ_DONE;
548}
549
550static int
551readVC( tr_handshake * handshake, struct evbuffer * inbuf )
552{
553    const uint8_t key[VC_LENGTH] = { 0, 0, 0, 0, 0, 0, 0, 0 };
554    const int key_len = VC_LENGTH;
555    uint8_t tmp[VC_LENGTH];
556
557    /* note: this works w/o having to `unwind' the buffer if
558     * we read too much, but it is pretty brute-force.
559     * it would be nice to make this cleaner. */
560    for( ;; )
561    {
562        if( EVBUFFER_LENGTH(inbuf) < VC_LENGTH ) {
563            fprintf( stderr, "not enough bytes... returning read_more\n" );
564            return READ_MORE;
565        }
566
567        memcpy( tmp, EVBUFFER_DATA(inbuf), key_len );
568        tr_cryptoDecryptInit( handshake->crypto );
569        tr_cryptoDecrypt( handshake->crypto, key_len, tmp, tmp );
570        if( !memcmp( tmp, key, key_len ) )
571            break;
572
573        evbuffer_drain( inbuf, 1 );
574    }
575
576    fprintf( stderr, "got it!\n" );
577    evbuffer_drain( inbuf, key_len );
578    setState( handshake, AWAITING_CRYPTO_SELECT );
579    return READ_AGAIN;
580}
581
582static int
583readCryptoSelect( tr_handshake * handshake, struct evbuffer * inbuf )
584{
585    uint32_t crypto_select;
586    uint16_t pad_d_len;
587    const size_t needlen = sizeof(uint32_t) + sizeof(uint16_t);
588
589    if( EVBUFFER_LENGTH(inbuf) < needlen )
590        return READ_MORE;
591
592    tr_peerIoReadUint32( handshake->io, inbuf, &crypto_select );
593    assert( crypto_select==1 || crypto_select==2 );
594    handshake->crypto_select = crypto_select;
595    fprintf( stderr, "crypto select is %d\n", crypto_select );
596
597    tr_peerIoReadUint16( handshake->io, inbuf, &pad_d_len );
598    fprintf( stderr, "pad_d_len is %d\n", (int)pad_d_len );
599    assert( pad_d_len <= 512 );
600    handshake->pad_d_len = pad_d_len;
601
602    setState( handshake, AWAITING_PAD_D );
603    return READ_AGAIN;
604}
605
606static int
607readPadD( tr_handshake * handshake, struct evbuffer * inbuf )
608{
609    const size_t needlen = handshake->pad_d_len;
610    uint8_t * tmp;
611
612fprintf( stderr, "pad d: need %d, got %d\n", (int)needlen, (int)EVBUFFER_LENGTH(inbuf) );
613    if( EVBUFFER_LENGTH(inbuf) < needlen )
614        return READ_MORE;
615
616    tmp = tr_new( uint8_t, needlen );
617    tr_peerIoReadBytes( handshake->io, inbuf, tmp, needlen );
618    tr_free( tmp );
619
620    tr_peerIoSetEncryption( handshake->io,
621                                    handshake->crypto_select );
622
623    setState( handshake, AWAITING_HANDSHAKE );
624    return READ_AGAIN;
625}
626
627/*ccc*/
628static int
629readHandshake( tr_handshake * handshake, struct evbuffer * inbuf )
630{
631    int i;
632    int ltep = 0;
633    int azmp = 0;
634    int isEncrypted;
635    uint8_t pstrlen;
636    uint8_t * pstr;
637    uint8_t reserved[8];
638    uint8_t hash[SHA_DIGEST_LENGTH];
639    uint8_t peer_id[20];
640    int bytesRead = 0;
641
642fprintf( stderr, "handshake payload: need %d, got %d\n", (int)HANDSHAKE_SIZE, (int)EVBUFFER_LENGTH(inbuf) );
643
644    if( EVBUFFER_LENGTH(inbuf) < HANDSHAKE_SIZE )
645        return READ_MORE;
646
647    /* pstrlen */
648    pstrlen = EVBUFFER_DATA(inbuf)[0];
649    fprintf( stderr, "pstrlen 1 is %d [%c]\n", (int)pstrlen, pstrlen );
650    isEncrypted = pstrlen != 19;
651    tr_peerIoSetEncryption( handshake->io, isEncrypted
652        ? PEER_ENCRYPTION_RC4
653        : PEER_ENCRYPTION_PLAINTEXT );
654    if( isEncrypted ) {
655        fprintf( stderr, "I guess it's encrypted...\n" );
656        if( tr_peerIoIsIncoming( handshake->io ) ) {
657            setState( handshake, AWAITING_YA );
658            return READ_AGAIN;
659        }
660        tr_cryptoDecrypt( handshake->crypto, 1, &pstrlen, &pstrlen );
661    }
662    bytesRead++;
663    evbuffer_drain( inbuf, 1 );
664    fprintf( stderr, "pstrlen is %d [%c]\n", (int)pstrlen, pstrlen );
665    assert( pstrlen == 19 );
666
667    /* pstr (BitTorrent) */
668    pstr = tr_new( uint8_t, pstrlen+1 );
669    tr_peerIoReadBytes( handshake->io, inbuf, pstr, pstrlen );
670    pstr[pstrlen] = '\0';
671    fprintf( stderr, "pstrlen is [%s]\n", pstr );
672    bytesRead += pstrlen;
673    assert( !strcmp( (char*)pstr, "BitTorrent protocol" ) );
674
675    /* reserved bytes */
676    tr_peerIoReadBytes( handshake->io, inbuf, reserved, sizeof(reserved) );
677    bytesRead += sizeof(reserved);
678
679    /* torrent hash */
680    tr_peerIoReadBytes( handshake->io, inbuf, hash, sizeof(hash) );
681    bytesRead += sizeof(hash);
682    if( tr_peerIoIsIncoming( handshake->io ) )
683    {
684        assert( !tr_peerIoHasTorrentHash( handshake->io ) );
685        tr_peerIoSetTorrentHash( handshake->io, hash );
686    }
687    else
688    {
689        assert( tr_peerIoHasTorrentHash( handshake->io ) );
690        assert( !memcmp( hash, tr_peerIoGetTorrentHash(handshake->io), SHA_DIGEST_LENGTH ) );
691    }
692
693    /* peer id */
694    tr_peerIoReadBytes( handshake->io, inbuf, peer_id, sizeof(peer_id) );
695//    fprintf( stderr, "peer_id: " );
696//    for( i=0; i<20; ++i ) fprintf( stderr, "[%c]", peer_id[i] );
697//    fprintf( stderr, "\n" );
698    tr_peerIoSetPeersId( handshake->io, peer_id );
699    bytesRead += sizeof(peer_id);
700
701    assert( bytesRead == HANDSHAKE_SIZE );
702
703    /**
704    ***
705    **/
706
707    ltep = HANDSHAKE_HAS_EXTMSGS( reserved ) ? 1 : 0;
708    azmp = HANDSHAKE_HAS_AZPROTO( reserved ) ? 1 : 0;
709    if( ltep && azmp ) {
710        switch( HANDSHAKE_GET_EXTPREF( reserved ) ) {
711            case HANDSHAKE_EXTPREF_LTEP_FORCE:
712            case HANDSHAKE_EXTPREF_LTEP_PREFER:
713                azmp = 0;
714                break;
715            case HANDSHAKE_EXTPREF_AZMP_FORCE:
716            case HANDSHAKE_EXTPREF_AZMP_PREFER:
717                ltep = 0;
718                break;
719        }
720    }
721    assert( !ltep || !azmp );
722         if( ltep ) { i = LT_EXTENSIONS_LTEP; fprintf(stderr,"using ltep\n" ); }
723    else if( azmp ) { i = LT_EXTENSIONS_AZMP; fprintf(stderr,"using azmp\n" ); }
724    else            { i = LT_EXTENSIONS_NONE; fprintf(stderr,"using no extensions\n" ); }
725    tr_peerIoSetExtension( handshake->io, i );
726
727
728    if( i == LT_EXTENSIONS_LTEP )
729    {
730        sendLtepHandshake( handshake );
731        return READ_DONE;
732    }
733    else if( !tr_peerIoIsIncoming( handshake->io ) && ( i != LT_EXTENSIONS_AZMP ) )
734    {
735        fireDoneCB( handshake, TRUE );
736        return READ_DONE;
737    }
738
739
740    fprintf( stderr, " UNHANDLED -- azmp " );
741    return 0;
742}
743
744/**
745***
746**/
747
748static ReadState
749canRead( struct bufferevent * evin, void * arg )
750{
751    tr_handshake * handshake = (tr_handshake *) arg;
752    struct evbuffer * inbuf = EVBUFFER_INPUT ( evin );
753    ReadState ret;
754    fprintf( stderr, "handshake %p handling canRead; state is [%s]\n", handshake, getStateName(handshake->state) );
755
756    switch( handshake->state )
757    {
758        case AWAITING_HANDSHAKE:       ret = readHandshake    ( handshake, inbuf ); break;
759        case AWAITING_YA:              ret = readYa           ( handshake, inbuf ); break;
760        case AWAITING_PAD_A:           ret = readPadA         ( handshake, inbuf ); break;
761        case AWAITING_CRYPTO_PROVIDE:  ret = readCryptoProvide( handshake, inbuf ); break;
762        case AWAITING_PAD_C:           ret = readPadC         ( handshake, inbuf ); break;
763        case AWAITING_IA:              ret = readIA           ( handshake, inbuf ); break;
764
765        case AWAITING_YB:              ret = readYb           ( handshake, inbuf ); break;
766        case AWAITING_VC:              ret = readVC           ( handshake, inbuf ); break;
767        case AWAITING_CRYPTO_SELECT:   ret = readCryptoSelect ( handshake, inbuf ); break;
768        case AWAITING_PAD_D:           ret = readPadD         ( handshake, inbuf ); break;
769
770        default: assert( 0 );
771    }
772
773    return ret;
774}
775
776static void
777didWrite( struct bufferevent * evin UNUSED, void * arg )
778{
779    tr_handshake * handshake = (tr_handshake *) arg;
780    fprintf( stderr, "handshake %p, with a state of %s, got a didWrite event\n", handshake, getStateName(handshake->state) );
781#if 0
782    abort ( );
783
784    if( handshake->state == SENDING_LTEP_HANDHAKE )
785    {
786        fireDoneCB( handshake, TRUE );
787    }
788    else
789    {
790cccccccccccccccccccccccccccccccccc
791        int state = -1;
792        switch( handshake->state )
793        {
794            //case SENDING_YA:                   state = AWAITING_YB; break;
795            //case SENDING_YB:                   state = AWAITING_PAD_A; break;
796            //case SENDING_CRYPTO_PROVIDE:       state = AWAITING_VC; break;
797            //case SENDING_PLAINTEXT_HANDSHAKE:  state = AWAITING_HANDSHAKE; break;
798        }
799        assert( state != -1 );
800        setState( handshake, state );
801        tr_peerIoReadOrWait( handshake->io );
802    }
803#endif
804}
805
806static void
807tr_handshakeFree( tr_handshake * handshake )
808{
809    /* FIXME */
810    tr_free( handshake );
811}
812
813static void
814fireDoneCB( tr_handshake * handshake, int isConnected )
815{
816fprintf( stderr, "handshake %p: firing done.  connected==%d\n", handshake, isConnected );
817    (*handshake->doneCB)(handshake->io, isConnected, handshake->doneUserData);
818    tr_handshakeFree( handshake );
819}
820
821static void
822gotError( struct bufferevent * evbuf UNUSED, short what, void * arg )
823{
824    tr_handshake * handshake = (tr_handshake *) arg;
825fprintf( stderr, "handshake %p: got error [%s]; what==%hd... state was [%s]\n", handshake, strerror(errno), what, getStateName(handshake->state) );
826
827
828    /* if the error happened while we were sending a public key, we might
829     * have encountered a peer that doesn't do encryption... reconnect and
830     * try a plaintext handshake */
831    if(    ( ( handshake->state == AWAITING_YB ) || ( handshake->state == AWAITING_VC ) )
832        && ( handshake->encryptionPreference != HANDSHAKE_ENCRYPTION_REQUIRED )
833        && ( !tr_peerIoReconnect( handshake->io ) ) )
834    {
835fprintf( stderr, "handshake %p trying again in plaintext...\n", handshake );
836        handshake->encryptionPreference = HANDSHAKE_PLAINTEXT_REQUIRED;
837        sendPlaintextHandshake( handshake );
838    }
839    else fireDoneCB( handshake, FALSE );
840}
841
842/**
843***
844**/
845
846static tr_handshake*
847tr_handshakeNew( tr_peerIo        * io,
848                 int                encryptionPreference,
849                 handshakeDoneCB    doneCB,
850                 void             * doneUserData )
851{
852    tr_handshake * handshake;
853
854//w00t
855//static int count = 0;
856//if( count++ ) return NULL;
857
858    handshake = tr_new0( tr_handshake, 1 );
859    handshake->io = io;
860    handshake->crypto = tr_peerIoGetCrypto( io );
861    handshake->encryptionPreference = encryptionPreference;
862    handshake->doneCB = doneCB;
863    handshake->doneUserData = doneUserData;
864    handshake->handle = tr_peerIoGetHandle( io );
865
866    tr_peerIoSetIOMode( io, EV_READ|EV_WRITE, 0 );
867    tr_peerIoSetIOFuncs( io, canRead, didWrite, gotError, handshake );
868
869fprintf( stderr, "handshake %p: new handshake for io %p\n", handshake, io );
870
871    if( tr_peerIoIsIncoming( io ) )
872    {
873        setReadState( handshake, AWAITING_HANDSHAKE );
874    }
875    else
876    {
877        //handshake->encryptionPreference = HANDSHAKE_PLAINTEXT_PREFERRED; /* this line is just for testing */
878        sendHandshake( handshake );
879    }
880
881    return handshake;
882}
883
884void
885tr_handshakeAdd( struct tr_peerIo * io,
886                 int                encryptionPreference,
887                 handshakeDoneCB    doneCB,   
888                 void             * doneUserData )
889{
890    tr_handshakeNew( io, encryptionPreference, doneCB, doneUserData );
891}
Note: See TracBrowser for help on using the repository browser.