From 125bd34bbb2a9c252cbbfa00c89406ac1c4df5f9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 8 Nov 2007 21:20:08 +0000 Subject: [PATCH] added `plaintext preferred' encryption option. --- libtransmission/handshake.c | 96 +++++++++++++++++++++++----------- libtransmission/transmission.h | 1 + 2 files changed, 66 insertions(+), 31 deletions(-) diff --git a/libtransmission/handshake.c b/libtransmission/handshake.c index 384687f45..b9c2fa554 100644 --- a/libtransmission/handshake.c +++ b/libtransmission/handshake.c @@ -89,13 +89,13 @@ struct tr_handshake { unsigned int havePeerID : 1; unsigned int haveSentBitTorrentHandshake : 1; - unsigned int allowUnencryptedPeers : 1; tr_peerIo * io; tr_crypto * crypto; struct tr_handle * handle; uint8_t myPublicKey[KEY_LEN]; uint8_t mySecret[KEY_LEN]; uint8_t state; + tr_encryption_mode encryptionMode; uint16_t pad_c_len; uint16_t pad_d_len; uint16_t ia_len; @@ -324,20 +324,53 @@ sendYa( tr_handshake * handshake ) } static uint32_t -getCryptoProvide( const tr_handshake * handshake UNUSED ) +getCryptoProvide( const tr_handshake * handshake ) { - uint32_t i = 0; + uint32_t provide = 0; - i |= CRYPTO_PROVIDE_CRYPTO; /* always allow crypto */ + switch( handshake->encryptionMode ) + { + case TR_ENCRYPTION_REQUIRED: + case TR_ENCRYPTION_PREFERRED: + provide |= CRYPTO_PROVIDE_CRYPTO; + break; -#if 0 - /* by the time we send a crypto_provide, we _know_ - * the peer supports encryption. */ - if( handshake->allowUnencryptedPeers ) - i |= CRYPTO_PROVIDE_PLAINTEXT; -#endif + case TR_PLAINTEXT_PREFERRED: + provide |= CRYPTO_PROVIDE_CRYPTO | CRYPTO_PROVIDE_PLAINTEXT; + break; + } - return i; + return provide; +} + +static uint32_t +getCryptoSelect( const tr_handshake * handshake, uint32_t crypto_provide ) +{ + uint32_t choices[4]; + int i, nChoices=0; + + switch( handshake->encryptionMode ) + { + case TR_ENCRYPTION_REQUIRED: + choices[nChoices++] = CRYPTO_PROVIDE_CRYPTO; + break; + + case TR_ENCRYPTION_PREFERRED: + choices[nChoices++] = CRYPTO_PROVIDE_CRYPTO; + choices[nChoices++] = CRYPTO_PROVIDE_PLAINTEXT; + break; + + case TR_PLAINTEXT_PREFERRED: + choices[nChoices++] = CRYPTO_PROVIDE_PLAINTEXT; + choices[nChoices++] = CRYPTO_PROVIDE_CRYPTO; + break; + } + + for( i=0; iio, PEER_ENCRYPTION_NONE ); - if( !handshake->allowUnencryptedPeers ) + if( handshake->encryptionMode == TR_ENCRYPTION_REQUIRED ) { dbgmsg( handshake, "peer is unencrypted, and we're disallowing that" ); tr_handshakeDone( handshake, FALSE ); @@ -840,23 +873,16 @@ dbgmsg( handshake, "sending vc" ); tr_peerIoWriteBytes( handshake->io, outbuf, vc, VC_LENGTH ); } -dbgmsg( handshake, "sending crypto_select" ); /* send crypto_select */ - { -dbgmsg( handshake, "handshake->crypto_provide is %d", (int)handshake->crypto_provide ); - if( handshake->crypto_provide & CRYPTO_PROVIDE_CRYPTO ) - crypto_select = CRYPTO_PROVIDE_CRYPTO; - else if( handshake->allowUnencryptedPeers ) - crypto_select = CRYPTO_PROVIDE_PLAINTEXT; - else { -dbgmsg( handshake, "gronk..." ); - evbuffer_free( outbuf ); - tr_handshakeDone( handshake, FALSE ); - return READ_DONE; - } - -dbgmsg( handshake, "we select crypto_select as %d...", (int)crypto_select ); + crypto_select = getCryptoSelect( handshake, handshake->crypto_provide ); + if( crypto_select ) { + dbgmsg( handshake, "selecting crypto mode '%d'", (int)crypto_select ); tr_peerIoWriteUint32( handshake->io, outbuf, crypto_select ); + } else { + dbgmsg( handshake, "peer didn't offer an encryption mode we like." ); + evbuffer_free( outbuf ); + tr_handshakeDone( handshake, FALSE ); + return READ_DONE; } dbgmsg( handshake, "sending pad d" ); @@ -964,7 +990,7 @@ gotError( struct bufferevent * evbuf UNUSED, short what, void * arg ) * have encountered a peer that doesn't do encryption... reconnect and * try a plaintext handshake */ if( ( ( handshake->state == AWAITING_YB ) || ( handshake->state == AWAITING_VC ) ) - && ( handshake->allowUnencryptedPeers ) + && ( handshake->encryptionMode != TR_ENCRYPTION_REQUIRED ) && ( !tr_peerIoReconnect( handshake->io ) ) ) { int msgSize; @@ -990,7 +1016,7 @@ gotError( struct bufferevent * evbuf UNUSED, short what, void * arg ) tr_handshake* tr_handshakeNew( tr_peerIo * io, - tr_encryption_mode encryption_mode, + tr_encryption_mode encryptionMode, handshakeDoneCB doneCB, void * doneUserData ) { @@ -999,7 +1025,7 @@ tr_handshakeNew( tr_peerIo * io, handshake = tr_new0( tr_handshake, 1 ); handshake->io = io; handshake->crypto = tr_peerIoGetCrypto( io ); - handshake->allowUnencryptedPeers = encryption_mode!=TR_ENCRYPTION_REQUIRED; + handshake->encryptionMode = encryptionMode; handshake->doneCB = doneCB; handshake->doneUserData = doneUserData; handshake->handle = tr_peerIoGetHandle( io ); @@ -1009,8 +1035,16 @@ tr_handshakeNew( tr_peerIo * io, if( tr_peerIoIsIncoming( handshake->io ) ) setReadState( handshake, AWAITING_HANDSHAKE ); - else + else if( encryptionMode != TR_PLAINTEXT_PREFERRED ) sendYa( handshake ); + else { + int msgSize; + uint8_t * msg = buildHandshakeMessage( handshake, &msgSize ); + handshake->haveSentBitTorrentHandshake = 1; + setReadState( handshake, AWAITING_HANDSHAKE ); + tr_peerIoWrite( handshake->io, msg, msgSize ); + tr_free( msg ); + } return handshake; } diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index f3d9d195d..dbf0553a7 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -116,6 +116,7 @@ typedef struct tr_tracker_info tr_tracker_info; typedef enum { + TR_PLAINTEXT_PREFERRED, TR_ENCRYPTION_PREFERRED, TR_ENCRYPTION_REQUIRED }