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 | |
---|
72 | extern const char* getPeerId( void ) ; |
---|
73 | |
---|
74 | #define KEY_LEN 96 |
---|
75 | #define PRIME_LEN 96 |
---|
76 | #define VC_LENGTH 8 |
---|
77 | |
---|
78 | |
---|
79 | typedef 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 | } |
---|
96 | tr_handshake; |
---|
97 | |
---|
98 | static void |
---|
99 | fireDoneCB( tr_handshake * handshake, int isConnected ); |
---|
100 | |
---|
101 | /** |
---|
102 | *** |
---|
103 | **/ |
---|
104 | |
---|
105 | enum /*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 | |
---|
126 | static 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 | |
---|
148 | static void |
---|
149 | setState( 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 | |
---|
155 | static void |
---|
156 | setReadState( tr_handshake * handshake, int state ) |
---|
157 | { |
---|
158 | setState( handshake, state ); |
---|
159 | //tr_peerIoSetIOMode( handshake->io, EV_READ, EV_WRITE ); |
---|
160 | } |
---|
161 | |
---|
162 | static void |
---|
163 | sendPublicKey( 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 | |
---|
192 | static void |
---|
193 | buildHandshakeMessage( 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 | |
---|
212 | static void |
---|
213 | sendPlaintextHandshake( 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 | |
---|
222 | static void |
---|
223 | sendHandshake( 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 | |
---|
236 | static void |
---|
237 | sendLtepHandshake( 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, <ep_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 | |
---|
283 | static int |
---|
284 | readYa( 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 | |
---|
314 | static int |
---|
315 | readPadA( 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 | |
---|
342 | static int |
---|
343 | readCryptoProvide( 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 | |
---|
392 | static int |
---|
393 | readPadC( 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 | |
---|
410 | static int |
---|
411 | readIA( 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 | |
---|
431 | static int |
---|
432 | readYb( 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; |
---|
442 | fprintf( 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 | |
---|
550 | static int |
---|
551 | readVC( 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 | |
---|
582 | static int |
---|
583 | readCryptoSelect( 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 | |
---|
606 | static int |
---|
607 | readPadD( tr_handshake * handshake, struct evbuffer * inbuf ) |
---|
608 | { |
---|
609 | const size_t needlen = handshake->pad_d_len; |
---|
610 | uint8_t * tmp; |
---|
611 | |
---|
612 | fprintf( 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*/ |
---|
628 | static int |
---|
629 | readHandshake( 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 | |
---|
642 | fprintf( 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 | |
---|
748 | static ReadState |
---|
749 | canRead( 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 | |
---|
776 | static void |
---|
777 | didWrite( 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 | { |
---|
790 | cccccccccccccccccccccccccccccccccc |
---|
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 | |
---|
806 | static void |
---|
807 | tr_handshakeFree( tr_handshake * handshake ) |
---|
808 | { |
---|
809 | /* FIXME */ |
---|
810 | tr_free( handshake ); |
---|
811 | } |
---|
812 | |
---|
813 | static void |
---|
814 | fireDoneCB( tr_handshake * handshake, int isConnected ) |
---|
815 | { |
---|
816 | fprintf( stderr, "handshake %p: firing done. connected==%d\n", handshake, isConnected ); |
---|
817 | (*handshake->doneCB)(handshake->io, isConnected, handshake->doneUserData); |
---|
818 | tr_handshakeFree( handshake ); |
---|
819 | } |
---|
820 | |
---|
821 | static void |
---|
822 | gotError( struct bufferevent * evbuf UNUSED, short what, void * arg ) |
---|
823 | { |
---|
824 | tr_handshake * handshake = (tr_handshake *) arg; |
---|
825 | fprintf( 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 | { |
---|
835 | fprintf( 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 | |
---|
846 | static tr_handshake* |
---|
847 | tr_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 | |
---|
869 | fprintf( 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 | |
---|
884 | void |
---|
885 | tr_handshakeAdd( struct tr_peerIo * io, |
---|
886 | int encryptionPreference, |
---|
887 | handshakeDoneCB doneCB, |
---|
888 | void * doneUserData ) |
---|
889 | { |
---|
890 | tr_handshakeNew( io, encryptionPreference, doneCB, doneUserData ); |
---|
891 | } |
---|