mirror of
https://github.com/transmission/transmission
synced 2025-03-04 02:28:03 +00:00
(trunk libT) #1734: encrypted peers' outgoing RC4 stream can be corrupted by sending protocol messages out-of-order
This commit is contained in:
parent
46aa5c6fc0
commit
b6c73370e3
3 changed files with 66 additions and 69 deletions
|
@ -456,6 +456,7 @@ readYb( tr_handshake * handshake,
|
|||
{
|
||||
uint8_t vc[VC_LENGTH] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
tr_peerIoWriteBuf( handshake->io, outbuf, FALSE );
|
||||
tr_cryptoEncryptInit( handshake->crypto );
|
||||
tr_peerIoSetEncryption( handshake->io, PEER_ENCRYPTION_RC4 );
|
||||
|
||||
|
@ -952,7 +953,10 @@ readIA( tr_handshake * handshake,
|
|||
|
||||
/* maybe de-encrypt our connection */
|
||||
if( crypto_select == CRYPTO_PROVIDE_PLAINTEXT )
|
||||
{
|
||||
tr_peerIoWriteBuf( handshake->io, outbuf, FALSE );
|
||||
tr_peerIoSetEncryption( handshake->io, PEER_ENCRYPTION_NONE );
|
||||
}
|
||||
|
||||
dbgmsg( handshake, "sending handshake" );
|
||||
/* send our handshake */
|
||||
|
@ -1174,6 +1178,7 @@ tr_handshakeNew( tr_peerIo * io,
|
|||
|
||||
tr_peerIoRef( io ); /* balanced by the unref in tr_handshakeFree */
|
||||
tr_peerIoSetIOFuncs( handshake->io, canRead, NULL, gotError, handshake );
|
||||
tr_peerIoSetEncryption( io, PEER_ENCRYPTION_NONE );
|
||||
|
||||
if( tr_peerIoIsIncoming( handshake->io ) )
|
||||
setReadState( handshake, AWAITING_HANDSHAKE );
|
||||
|
|
|
@ -649,71 +649,60 @@ tr_peerIoSetEncryption( tr_peerIo * io,
|
|||
|
||||
void
|
||||
tr_peerIoWrite( tr_peerIo * io,
|
||||
const void * writeme,
|
||||
size_t writemeLen,
|
||||
int isPieceData )
|
||||
const void * bytes,
|
||||
size_t byteCount,
|
||||
tr_bool isPieceData )
|
||||
{
|
||||
struct tr_datatype * datatype;
|
||||
|
||||
assert( tr_amInEventThread( io->session ) );
|
||||
dbgmsg( io, "adding %zu bytes into io->output", writemeLen );
|
||||
dbgmsg( io, "adding %zu bytes into io->output", byteCount );
|
||||
|
||||
datatype = tr_new( struct tr_datatype, 1 );
|
||||
datatype->isPieceData = isPieceData != 0;
|
||||
datatype->length = writemeLen;
|
||||
datatype->length = byteCount;
|
||||
|
||||
__tr_list_init( &datatype->head );
|
||||
__tr_list_append( &io->outbuf_datatypes, &datatype->head );
|
||||
|
||||
evbuffer_add( io->outbuf, writeme, writemeLen );
|
||||
}
|
||||
|
||||
void
|
||||
tr_peerIoWriteBuf( tr_peerIo * io,
|
||||
struct evbuffer * buf,
|
||||
int isPieceData )
|
||||
{
|
||||
const size_t n = EVBUFFER_LENGTH( buf );
|
||||
tr_peerIoWrite( io, EVBUFFER_DATA( buf ), n, isPieceData );
|
||||
evbuffer_drain( buf, n );
|
||||
}
|
||||
|
||||
/**
|
||||
***
|
||||
**/
|
||||
|
||||
void
|
||||
tr_peerIoWriteBytes( tr_peerIo * io,
|
||||
struct evbuffer * outbuf,
|
||||
const void * bytes,
|
||||
size_t byteCount )
|
||||
{
|
||||
uint8_t tmp[MAX_STACK_ARRAY_SIZE];
|
||||
|
||||
switch( io->encryptionMode )
|
||||
{
|
||||
case PEER_ENCRYPTION_NONE:
|
||||
evbuffer_add( outbuf, bytes, byteCount );
|
||||
break;
|
||||
|
||||
case PEER_ENCRYPTION_RC4: {
|
||||
case PEER_ENCRYPTION_RC4:
|
||||
{
|
||||
uint8_t tmp[MAX_STACK_ARRAY_SIZE];
|
||||
const uint8_t * walk = bytes;
|
||||
evbuffer_expand( outbuf, byteCount );
|
||||
while( byteCount > 0 ) {
|
||||
evbuffer_expand( io->outbuf, byteCount );
|
||||
while( byteCount > 0 )
|
||||
{
|
||||
const size_t thisPass = MIN( byteCount, sizeof( tmp ) );
|
||||
tr_cryptoEncrypt( io->crypto, thisPass, walk, tmp );
|
||||
evbuffer_add( outbuf, tmp, thisPass );
|
||||
evbuffer_add( io->outbuf, tmp, thisPass );
|
||||
walk += thisPass;
|
||||
byteCount -= thisPass;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PEER_ENCRYPTION_NONE:
|
||||
evbuffer_add( io->outbuf, bytes, byteCount );
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tr_peerIoWriteBuf( tr_peerIo * io,
|
||||
struct evbuffer * buf,
|
||||
tr_bool isPieceData )
|
||||
{
|
||||
const size_t n = EVBUFFER_LENGTH( buf );
|
||||
tr_peerIoWrite( io, EVBUFFER_DATA( buf ), n, isPieceData );
|
||||
evbuffer_drain( buf, n );
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
|
|
@ -224,11 +224,11 @@ void tr_peerIoClear ( tr_peerIo * io );
|
|||
void tr_peerIoWrite ( tr_peerIo * io,
|
||||
const void * writeme,
|
||||
size_t writemeLen,
|
||||
int isPieceData );
|
||||
tr_bool isPieceData );
|
||||
|
||||
void tr_peerIoWriteBuf ( tr_peerIo * io,
|
||||
struct evbuffer * buf,
|
||||
int isPieceData );
|
||||
tr_bool isPieceData );
|
||||
|
||||
/**
|
||||
***
|
||||
|
@ -255,67 +255,70 @@ static TR_INLINE tr_bool tr_peerIoIsEncrypted( const tr_peerIo * io )
|
|||
return ( io != NULL ) && ( io->encryptionMode == PEER_ENCRYPTION_RC4 );
|
||||
}
|
||||
|
||||
void tr_peerIoWriteBytes( tr_peerIo * io,
|
||||
struct evbuffer * outbuf,
|
||||
const void * bytes,
|
||||
size_t byteCount );
|
||||
static TR_INLINE void tr_peerIoWriteBytes( tr_peerIo * io UNUSED,
|
||||
struct evbuffer * outbuf,
|
||||
const void * bytes,
|
||||
size_t byteCount )
|
||||
{
|
||||
evbuffer_add( outbuf, bytes, byteCount );
|
||||
}
|
||||
|
||||
static TR_INLINE void tr_peerIoWriteUint8( tr_peerIo * io,
|
||||
struct evbuffer * outbuf,
|
||||
uint8_t writeme )
|
||||
static TR_INLINE void tr_peerIoWriteUint8( tr_peerIo * io,
|
||||
struct evbuffer * outbuf,
|
||||
uint8_t writeme )
|
||||
{
|
||||
tr_peerIoWriteBytes( io, outbuf, &writeme, sizeof( uint8_t ) );
|
||||
}
|
||||
|
||||
static TR_INLINE void tr_peerIoWriteUint16( tr_peerIo * io,
|
||||
struct evbuffer * outbuf,
|
||||
uint16_t writeme )
|
||||
static TR_INLINE void tr_peerIoWriteUint16( tr_peerIo * io,
|
||||
struct evbuffer * outbuf,
|
||||
uint16_t writeme )
|
||||
{
|
||||
const uint16_t tmp = htons( writeme );
|
||||
tr_peerIoWriteBytes( io, outbuf, &tmp, sizeof( uint16_t ) );
|
||||
}
|
||||
|
||||
static TR_INLINE void tr_peerIoWriteUint32( tr_peerIo * io,
|
||||
struct evbuffer * outbuf,
|
||||
uint32_t writeme )
|
||||
static TR_INLINE void tr_peerIoWriteUint32( tr_peerIo * io,
|
||||
struct evbuffer * outbuf,
|
||||
uint32_t writeme )
|
||||
{
|
||||
const uint32_t tmp = htonl( writeme );
|
||||
tr_peerIoWriteBytes( io, outbuf, &tmp, sizeof( uint32_t ) );
|
||||
}
|
||||
|
||||
void tr_peerIoReadBytes( tr_peerIo * io,
|
||||
struct evbuffer * inbuf,
|
||||
void * bytes,
|
||||
size_t byteCount );
|
||||
void tr_peerIoReadBytes( tr_peerIo * io,
|
||||
struct evbuffer * inbuf,
|
||||
void * bytes,
|
||||
size_t byteCount );
|
||||
|
||||
static TR_INLINE void tr_peerIoReadUint8( tr_peerIo * io,
|
||||
struct evbuffer * inbuf,
|
||||
uint8_t * setme )
|
||||
static TR_INLINE void tr_peerIoReadUint8( tr_peerIo * io,
|
||||
struct evbuffer * inbuf,
|
||||
uint8_t * setme )
|
||||
{
|
||||
tr_peerIoReadBytes( io, inbuf, setme, sizeof( uint8_t ) );
|
||||
}
|
||||
|
||||
static TR_INLINE void tr_peerIoReadUint16( tr_peerIo * io,
|
||||
struct evbuffer * inbuf,
|
||||
uint16_t * setme )
|
||||
static TR_INLINE void tr_peerIoReadUint16( tr_peerIo * io,
|
||||
struct evbuffer * inbuf,
|
||||
uint16_t * setme )
|
||||
{
|
||||
uint16_t tmp;
|
||||
tr_peerIoReadBytes( io, inbuf, &tmp, sizeof( uint16_t ) );
|
||||
*setme = ntohs( tmp );
|
||||
}
|
||||
|
||||
static TR_INLINE void tr_peerIoReadUint32( tr_peerIo * io,
|
||||
struct evbuffer * inbuf,
|
||||
uint32_t * setme )
|
||||
static TR_INLINE void tr_peerIoReadUint32( tr_peerIo * io,
|
||||
struct evbuffer * inbuf,
|
||||
uint32_t * setme )
|
||||
{
|
||||
uint32_t tmp;
|
||||
tr_peerIoReadBytes( io, inbuf, &tmp, sizeof( uint32_t ) );
|
||||
*setme = ntohl( tmp );
|
||||
}
|
||||
|
||||
void tr_peerIoDrain( tr_peerIo * io,
|
||||
struct evbuffer * inbuf,
|
||||
size_t byteCount );
|
||||
void tr_peerIoDrain( tr_peerIo * io,
|
||||
struct evbuffer * inbuf,
|
||||
size_t byteCount );
|
||||
|
||||
/**
|
||||
***
|
||||
|
|
Loading…
Add table
Reference in a new issue