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

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

still way too buggy, but I can now seed at full speed using < 2% of the CPU. =)

  • Property svn:keywords set to Date Rev Author Id
File size: 26.6 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 2978 2007-09-06 00:33:33Z 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    evbuffer_remove( inbuf, &pstrlen, 1 );
649    bytesRead++;
650    fprintf( stderr, "pstrlen 1 is %d [%c]\n", (int)pstrlen, pstrlen );
651    isEncrypted = pstrlen != 19;
652    tr_peerIoSetEncryption( handshake->io, isEncrypted
653        ? PEER_ENCRYPTION_RC4
654        : PEER_ENCRYPTION_PLAINTEXT );
655    if( isEncrypted ) {
656        fprintf( stderr, "I guess it's encrypted...\n" );
657        tr_cryptoDecrypt( handshake->crypto, 1, &pstrlen, &pstrlen );
658    }
659    fprintf( stderr, "pstrlen is %d [%c]\n", (int)pstrlen, pstrlen );
660    assert( pstrlen == 19 );
661
662    /* pstr (BitTorrent) */
663    pstr = tr_new( uint8_t, pstrlen+1 );
664    tr_peerIoReadBytes( handshake->io, inbuf, pstr, pstrlen );
665    pstr[pstrlen] = '\0';
666    fprintf( stderr, "pstrlen is [%s]\n", pstr );
667    bytesRead += pstrlen;
668    assert( !strcmp( (char*)pstr, "BitTorrent protocol" ) );
669
670    /* reserved bytes */
671    tr_peerIoReadBytes( handshake->io, inbuf, reserved, sizeof(reserved) );
672    bytesRead += sizeof(reserved);
673
674    /* torrent hash */
675    tr_peerIoReadBytes( handshake->io, inbuf, hash, sizeof(hash) );
676    assert( !memcmp( hash, tr_peerIoGetTorrentHash(handshake->io), SHA_DIGEST_LENGTH ) );
677    bytesRead += sizeof(hash);
678
679    /* peer id */
680    tr_peerIoReadBytes( handshake->io, inbuf, peer_id, sizeof(peer_id) );
681//    fprintf( stderr, "peer_id: " );
682//    for( i=0; i<20; ++i ) fprintf( stderr, "[%c]", peer_id[i] );
683//    fprintf( stderr, "\n" );
684    tr_peerIoSetPeersId( handshake->io, peer_id );
685    bytesRead += sizeof(peer_id);
686
687    assert( bytesRead == HANDSHAKE_SIZE );
688
689    /**
690    ***
691    **/
692
693    ltep = HANDSHAKE_HAS_EXTMSGS( reserved ) ? 1 : 0;
694    azmp = HANDSHAKE_HAS_AZPROTO( reserved ) ? 1 : 0;
695    if( ltep && azmp ) {
696        switch( HANDSHAKE_GET_EXTPREF( reserved ) ) {
697            case HANDSHAKE_EXTPREF_LTEP_FORCE:
698            case HANDSHAKE_EXTPREF_LTEP_PREFER:
699                azmp = 0;
700                break;
701            case HANDSHAKE_EXTPREF_AZMP_FORCE:
702            case HANDSHAKE_EXTPREF_AZMP_PREFER:
703                ltep = 0;
704                break;
705        }
706    }
707    assert( !ltep || !azmp );
708         if( ltep ) { i = LT_EXTENSIONS_LTEP; fprintf(stderr,"using ltep\n" ); }
709    else if( azmp ) { i = LT_EXTENSIONS_AZMP; fprintf(stderr,"using azmp\n" ); }
710    else            { i = LT_EXTENSIONS_NONE; fprintf(stderr,"using no extensions\n" ); }
711    tr_peerIoSetExtension( handshake->io, i );
712
713
714    if( i == LT_EXTENSIONS_LTEP )
715    {
716        sendLtepHandshake( handshake );
717        return READ_DONE;
718    }
719    else if( !tr_peerIoIsIncoming( handshake->io ) && ( i != LT_EXTENSIONS_AZMP ) )
720    {
721        fireDoneCB( handshake, TRUE );
722        return READ_DONE;
723    }
724
725
726    fprintf( stderr, " UNHANDLED -- azmp " );
727    return 0;
728}
729
730/**
731***
732**/
733
734static ReadState
735canRead( struct bufferevent * evin, void * arg )
736{
737    tr_handshake * handshake = (tr_handshake *) arg;
738    struct evbuffer * inbuf = EVBUFFER_INPUT ( evin );
739    ReadState ret;
740    fprintf( stderr, "handshake %p handling canRead; state is [%s]\n", handshake, getStateName(handshake->state) );
741
742    switch( handshake->state )
743    {
744        case AWAITING_HANDSHAKE:       ret = readHandshake    ( handshake, inbuf ); break;
745        case AWAITING_YA:              ret = readYa           ( handshake, inbuf ); break;
746        case AWAITING_PAD_A:           ret = readPadA         ( handshake, inbuf ); break;
747        case AWAITING_CRYPTO_PROVIDE:  ret = readCryptoProvide( handshake, inbuf ); break;
748        case AWAITING_PAD_C:           ret = readPadC         ( handshake, inbuf ); break;
749        case AWAITING_IA:              ret = readIA           ( handshake, inbuf ); break;
750
751        case AWAITING_YB:              ret = readYb           ( handshake, inbuf ); break;
752        case AWAITING_VC:              ret = readVC           ( handshake, inbuf ); break;
753        case AWAITING_CRYPTO_SELECT:   ret = readCryptoSelect ( handshake, inbuf ); break;
754        case AWAITING_PAD_D:           ret = readPadD         ( handshake, inbuf ); break;
755
756        default: assert( 0 );
757    }
758
759    return ret;
760}
761
762static void
763didWrite( struct bufferevent * evin UNUSED, void * arg )
764{
765    tr_handshake * handshake = (tr_handshake *) arg;
766    fprintf( stderr, "handshake %p, with a state of %s, got a didWrite event\n", handshake, getStateName(handshake->state) );
767#if 0
768    abort ( );
769
770    if( handshake->state == SENDING_LTEP_HANDHAKE )
771    {
772        fireDoneCB( handshake, TRUE );
773    }
774    else
775    {
776cccccccccccccccccccccccccccccccccc
777        int state = -1;
778        switch( handshake->state )
779        {
780            //case SENDING_YA:                   state = AWAITING_YB; break;
781            //case SENDING_YB:                   state = AWAITING_PAD_A; break;
782            //case SENDING_CRYPTO_PROVIDE:       state = AWAITING_VC; break;
783            //case SENDING_PLAINTEXT_HANDSHAKE:  state = AWAITING_HANDSHAKE; break;
784        }
785        assert( state != -1 );
786        setState( handshake, state );
787        tr_peerIoReadOrWait( handshake->io );
788    }
789#endif
790}
791
792static void
793tr_handshakeFree( tr_handshake * handshake )
794{
795    /* FIXME */
796    tr_free( handshake );
797}
798
799static void
800fireDoneCB( tr_handshake * handshake, int isConnected )
801{
802fprintf( stderr, "handshake %p: firing done.  connected==%d\n", handshake, isConnected );
803    (*handshake->doneCB)(handshake->io, isConnected, handshake->doneUserData);
804    tr_handshakeFree( handshake );
805}
806
807static void
808gotError( struct bufferevent * evbuf UNUSED, short what, void * arg )
809{
810    tr_handshake * handshake = (tr_handshake *) arg;
811fprintf( stderr, "handshake %p: got error [%s]; what==%hd... state was [%s]\n", handshake, strerror(errno), what, getStateName(handshake->state) );
812
813
814    /* if the error happened while we were sending a public key, we might
815     * have encountered a peer that doesn't do encryption... reconnect and
816     * try a plaintext handshake */
817    if(    ( ( handshake->state == AWAITING_YB ) || ( handshake->state == AWAITING_VC ) )
818        && ( handshake->encryptionPreference != HANDSHAKE_ENCRYPTION_REQUIRED )
819        && ( !tr_peerIoReconnect( handshake->io ) ) )
820    {
821fprintf( stderr, "handshake %p trying again in plaintext...\n", handshake );
822        handshake->encryptionPreference = HANDSHAKE_PLAINTEXT_REQUIRED;
823        sendPlaintextHandshake( handshake );
824    }
825    else fireDoneCB( handshake, FALSE );
826}
827
828/**
829***
830**/
831
832static tr_handshake*
833tr_handshakeNew( tr_peerIo        * io,
834                 int                encryptionPreference,
835                 handshakeDoneCB    doneCB,
836                 void             * doneUserData )
837{
838    tr_handshake * handshake;
839
840//w00t
841//static int count = 0;
842//if( count++ ) return NULL;
843
844    handshake = tr_new0( tr_handshake, 1 );
845    handshake->io = io;
846    handshake->crypto = tr_peerIoGetCrypto( io );
847    handshake->encryptionPreference = encryptionPreference;
848    handshake->doneCB = doneCB;
849    handshake->doneUserData = doneUserData;
850    handshake->handle = tr_peerIoGetHandle( io );
851
852    tr_peerIoSetIOMode( io, EV_READ|EV_WRITE, 0 );
853    tr_peerIoSetIOFuncs( io, canRead, didWrite, gotError, handshake );
854
855fprintf( stderr, "handshake %p: new handshake for io %p\n", handshake, io );
856
857    if( tr_peerIoIsIncoming( io ) )
858    {
859        setReadState( handshake, AWAITING_HANDSHAKE );
860    }
861    else
862    {
863        //handshake->encryptionPreference = HANDSHAKE_PLAINTEXT_PREFERRED; /* this line is just for testing */
864        sendHandshake( handshake );
865    }
866
867    return handshake;
868}
869
870void
871tr_handshakeAdd( struct tr_peerIo * io,
872                 int                encryptionPreference,
873                 handshakeDoneCB    doneCB,   
874                 void             * doneUserData )
875{
876    tr_handshakeNew( io, encryptionPreference, doneCB, doneUserData );
877}
Note: See TracBrowser for help on using the repository browser.