/pidgin/main: 6d984b02fa91: Merged in rw_grim/pidgin-security (p...
Gary Kramlich <[email protected]> Mon, 20 Jun 2016 20:09:59 -0400
| Newsgroups | gmane.comp.gnome.gaim.cvs |
|---|---|
| Message-ID | <[email protected]> |
Changeset: 6d984b02fa91ff9afa4ef38594b5da6a4479a8cf Author: Gary Kramlich <[email protected]> Date: 2016-06-12 21:57 -0500 Branch: release-2.x.y URL: https://hg.pidgin.im/pidgin/main/rev/6d984b02fa91 Description: Merged in rw_grim/pidgin-security (pull request #11) TALOS-CAN-0120 TALOS-CAN-0135 TALOS-CAN-0138 and TALOS-CAN-0140 diffstat: ChangeLog | 8 + libpurple/protocols/mxit/chunk.c | 259 +++++++++++++++++++++---------- libpurple/protocols/mxit/chunk.h | 79 ++++---- libpurple/protocols/mxit/filexfer.c | 6 +- libpurple/protocols/mxit/filexfer.h | 4 +- libpurple/protocols/mxit/protocol.c | 225 +++++++++++--------------- libpurple/protocols/mxit/protocol.h | 8 +- libpurple/protocols/mxit/splashscreen.c | 2 +- libpurple/protocols/mxit/splashscreen.h | 2 +- 9 files changed, 326 insertions(+), 267 deletions(-) diffs (truncated from 1189 to 300 lines): diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,14 @@ version 2.10.13 (MM/DD/YY): Bonjour * Fixed building on Mac OSX (Patrick Cloke) (#16883) + MXit + * Fixed a buffer overflow. Discovered by Yves Younan of Cisco Talos. + (TALOS-CAN-0120) + * Fixed a remote out-of-bounds read. Discovered by Yves Younan of Cisco + Talos. (TALOS-CAN-0140) + * Fixed a remote out-of-band read. Discovered by Yves Younan of Cisco + Talos. (TALOS-CAN-0138, TALOS-CAN-0135) + version 2.10.12 (12/31/15): General: * purple-url-handler now works with Python 3.x (Daniël van Eeden) diff --git a/libpurple/protocols/mxit/chunk.c b/libpurple/protocols/mxit/chunk.c --- a/libpurple/protocols/mxit/chunk.c +++ b/libpurple/protocols/mxit/chunk.c @@ -151,11 +151,15 @@ static int add_utf8_string( char* chunkd * Extract a single byte from the chunked data. * * @param chunkdata The chunked-data buffer + * @param chunklen The amount of data available in the buffer. * @param value The byte * @return The number of bytes extracted. */ -static int get_int8( const char* chunkdata, char* value ) +static int get_int8( const char* chunkdata, size_t chunklen, char* value ) { + if ( chunklen < sizeof( char ) ) + return 0; + *value = *chunkdata; return sizeof( char ); @@ -165,11 +169,15 @@ static int get_int8( const char* chunkda * Extract a 16-bit value from the chunked data. * * @param chunkdata The chunked-data buffer + * @param chunklen The amount of data available in the buffer. * @param value The 16-bit value * @return The number of bytes extracted */ -static int get_int16( const char* chunkdata, short* value ) +static int get_int16( const char* chunkdata, size_t chunklen, unsigned short* value ) { + if ( chunklen < sizeof( short ) ) + return 0; + *value = ntohs( *( (const short*) chunkdata ) ); /* host byte-order */ return sizeof( short ); @@ -179,11 +187,15 @@ static int get_int16( const char* chunkd * Extract a 32-bit value from the chunked data. * * @param chunkdata The chunked-data buffer + * @param chunklen The amount of data available in the buffer. * @param value The 32-bit value * @return The number of bytes extracted */ -static int get_int32( const char* chunkdata, int* value ) +static int get_int32( const char* chunkdata, size_t chunklen, unsigned int* value ) { + if ( chunklen < sizeof( int ) ) + return 0; + *value = ntohl( *( (const int*) chunkdata ) ); /* host byte-order */ return sizeof( int ); @@ -194,11 +206,15 @@ static int get_int32( const char* chunkd * Extract a 64-bit value from the chunked data. * * @param chunkdata The chunked-data buffer + * @param chunklen The amount of data available in the buffer. * @param value The 64-bit value * @return The number of bytes extracted */ -static int get_int64( const char* chunkdata, int64_t* value ) +static int get_int64( const char* chunkdata, size_t chunklen, int64_t* value ) { + if ( chunklen < sizeof( int64_t ) ) + return 0; + *value = SWAP_64( *( (const int64_t*) chunkdata ) ); /* host byte-order */ return sizeof( int64_t ); @@ -209,12 +225,16 @@ static int get_int64( const char* chunkd * Copy a block of data from the chunked data. * * @param chunkdata The chunked-data buffer + * @param chunklen The amount of data available in the buffer. * @param dest Where to store the extract data * @param datalen The length of the data to extract * @return The number of bytes extracted */ -static int get_data( const char* chunkdata, char* dest, int datalen ) +static int get_data( const char* chunkdata, size_t chunklen, char* dest, size_t datalen ) { + if ( chunklen < datalen ) + return 0; + memcpy( dest, chunkdata, datalen ); return datalen; @@ -224,20 +244,25 @@ static int get_data( const char* chunkda * Extract a UTF-8 encoded string from the chunked data. * * @param chunkdata The chunked-data buffer + * @param chunklen The amount of data available in the buffer. * @param str A pointer to extracted string. Must be g_free()'d. * @param maxstrlen Maximum size of destination buffer. * @return The number of bytes consumed */ -static int get_utf8_string( const char* chunkdata, char* str, int maxstrlen ) +static int get_utf8_string( const char* chunkdata, size_t chunklen, char* str, size_t maxstrlen ) { - int pos = 0; - short len; - int skip = 0; + size_t pos = 0; + unsigned short len = 0; + size_t skip = 0; /* string length [2 bytes] */ - pos += get_int16( &chunkdata[pos], &len ); + pos += get_int16( &chunkdata[pos], chunklen - pos, &len ); - if ( len > maxstrlen ) { + if ( ( len + pos ) > chunklen ) { + /* string length is longer than chunk size */ + return 0; + } + else if ( len > maxstrlen ) { /* possible buffer overflow */ purple_debug_error( MXIT_PLUGIN_ID, "Buffer overflow detected (get_utf8_string)\n" ); skip = len - maxstrlen; @@ -245,7 +270,7 @@ static int get_utf8_string( const char* } /* string data */ - pos += get_data( &chunkdata[pos], str, len ); + pos += get_data( &chunkdata[pos], chunklen - pos, str, len ); str[len] = '\0'; /* terminate string */ return pos + skip; @@ -263,9 +288,9 @@ static int get_utf8_string( const char* * @param fileid A unique ID that identifies this file * @return The number of bytes encoded in the buffer */ -int mxit_chunk_create_reject( char* chunkdata, const char* fileid ) +size_t mxit_chunk_create_reject( char* chunkdata, const char* fileid ) { - int pos = 0; + size_t pos = 0; /* file id [8 bytes] */ pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN ); @@ -289,9 +314,9 @@ int mxit_chunk_create_reject( char* chun * @param offset The start offset in the file * @return The number of bytes encoded in the buffer */ -int mxit_chunk_create_get( char* chunkdata, const char* fileid, int filesize, int offset ) +size_t mxit_chunk_create_get( char* chunkdata, const char* fileid, size_t filesize, size_t offset ) { - int pos = 0; + size_t pos = 0; /* file id [8 bytes] */ pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN ); @@ -314,9 +339,9 @@ int mxit_chunk_create_get( char* chunkda * @param status The status of the file transfer (see chunk.h) * @return The number of bytes encoded in the buffer */ -int mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status ) +size_t mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status ) { - int pos = 0; + size_t pos = 0; /* file id [8 bytes] */ pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN ); @@ -338,9 +363,9 @@ int mxit_chunk_create_received( char* ch * @param datalen The size of the file contents * @return The number of bytes encoded in the buffer */ -int mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, int datalen ) +size_t mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, size_t datalen ) { - int pos = 0; + size_t pos = 0; const char* mime = NULL; /* data length [4 bytes] */ @@ -380,10 +405,10 @@ int mxit_chunk_create_senddirect( char* * @param datalen The size of the avatar data * @return The number of bytes encoded in the buffer */ -int mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, int datalen ) +size_t mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, size_t datalen ) { char fileid[MXIT_CHUNK_FILEID_LEN]; - int pos = 0; + size_t pos = 0; /* id [8 bytes] */ memset( &fileid, 0, sizeof( fileid ) ); /* set to 0 for file upload */ @@ -410,9 +435,9 @@ int mxit_chunk_create_set_avatar( char* * @param avatarId The Id of the avatar image (as string) * @return The number of bytes encoded in the buffer */ -int mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId ) +size_t mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId ) { - int pos = 0; + size_t pos = 0; /* number of avatars [4 bytes] */ pos += add_int32( &chunkdata[pos], 1 ); @@ -449,28 +474,31 @@ int mxit_chunk_create_get_avatar( char* * @param chunkdata Chunked data buffer * @param datalen The length of the chunked data * @param offer Decoded offerfile information + * @return TRUE if successfully parsed, otherwise FALSE */ -void mxit_chunk_parse_offer( char* chunkdata, int datalen, struct offerfile_chunk* offer ) +gboolean mxit_chunk_parse_offer( char* chunkdata, size_t datalen, struct offerfile_chunk* offer ) { - int pos = 0; + size_t pos = 0; - purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_offer (%i bytes)\n", datalen ); + purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_offer (%zu bytes)\n", datalen ); + + memset( offer, 0, sizeof( struct offerfile_chunk ) ); /* id [8 bytes] */ - pos += get_data( &chunkdata[pos], offer->fileid, 8); + pos += get_data( &chunkdata[pos], datalen - pos, offer->fileid, 8); /* from username [UTF-8] */ - pos += get_utf8_string( &chunkdata[pos], offer->username, sizeof( offer->username ) ); + pos += get_utf8_string( &chunkdata[pos], datalen - pos, offer->username, sizeof( offer->username ) ); mxit_strip_domain( offer->username ); /* file size [4 bytes] */ - pos += get_int32( &chunkdata[pos], &(offer->filesize) ); + pos += get_int32( &chunkdata[pos], datalen - pos, &(offer->filesize) ); /* filename [UTF-8] */ - pos += get_utf8_string( &chunkdata[pos], offer->filename, sizeof( offer->filename ) ); + pos += get_utf8_string( &chunkdata[pos], datalen - pos, offer->filename, sizeof( offer->filename ) ); /* mime type [UTF-8] */ - pos += get_utf8_string( &chunkdata[pos], offer->mimetype, sizeof( offer->mimetype ) ); + pos += get_utf8_string( &chunkdata[pos], datalen - pos, offer->mimetype, sizeof( offer->mimetype ) ); /* timestamp [8 bytes] */ /* not used by libPurple */ @@ -483,6 +511,8 @@ void mxit_chunk_parse_offer( char* chunk /* flags [4 bytes] */ /* not used by libPurple */ + + return TRUE; } @@ -492,27 +522,41 @@ void mxit_chunk_parse_offer( char* chunk * @param chunkdata Chunked data buffer * @param datalen The length of the chunked data * @param offer Decoded getfile information + * @return TRUE if successfully parsed, otherwise FALSE */ -void mxit_chunk_parse_get( char* chunkdata, int datalen, struct getfile_chunk* getfile ) +gboolean mxit_chunk_parse_get( char* chunkdata, size_t datalen, struct getfile_chunk* getfile ) { - int pos = 0; + size_t pos = 0; - purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_file (%i bytes)\n", datalen ); + purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_file (%zu bytes)\n", datalen ); + + memset( getfile, 0, sizeof( struct getfile_chunk ) ); + + /* ensure that the chunk size is atleast the minimum size for a "get file" chunk */ + if ( datalen < 20 ) + return FALSE; /* id [8 bytes] */ - pos += get_data( &chunkdata[pos], getfile->fileid, 8 ); + pos += get_data( &chunkdata[pos], datalen - pos, getfile->fileid, 8 ); /* offset [4 bytes] */ - pos += get_int32( &chunkdata[pos], &(getfile->offset) ); + pos += get_int32( &chunkdata[pos], datalen - pos, &(getfile->offset) ); /* file length [4 bytes] */ _______________________________________________ Commits mailing list [email protected] https://pidgin.im/cgi-bin/mailman/listinfo/commits