(trunk libT) #1734: encrypted peers' outgoing RC4 stream can be corrupted by sending protocol messages out-of-order

This commit is contained in:
Charles Kerr 2009-01-22 14:32:29 +00:00
parent 46aa5c6fc0
commit b6c73370e3
3 changed files with 66 additions and 69 deletions

View File

@ -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 );

View File

@ -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 );
}
/***
****
***/

View File

@ -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 );
/**
***