diff options
author | Gary Kramlich <grim@reaperworld.com> | 2016-06-12 22:13:22 -0500 |
---|---|---|
committer | Gary Kramlich <grim@reaperworld.com> | 2016-06-12 22:13:22 -0500 |
commit | 92bfd36660efe20244c9a6eee8ecabc0e8ec94b2 (patch) | |
tree | 2d9dbd130cde2903d6d870244016ad3ae94398c8 | |
parent | 1b928a66f0232752c3b32fc01b4165eef0a38544 (diff) | |
parent | 9bc29eb2dfe1db46807d0e5c24d62f3cbdee526e (diff) | |
download | pidgin-92bfd36660efe20244c9a6eee8ecabc0e8ec94b2.tar.gz |
Merged TALOS-CAN-0134
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | libpurple/plugins/ssl/ssl-gnutls.c | 16 | ||||
-rw-r--r-- | libpurple/protocols/mxit/chunk.c | 259 | ||||
-rw-r--r-- | libpurple/protocols/mxit/chunk.h | 79 | ||||
-rw-r--r-- | libpurple/protocols/mxit/filexfer.c | 6 | ||||
-rw-r--r-- | libpurple/protocols/mxit/filexfer.h | 4 | ||||
-rw-r--r-- | libpurple/protocols/mxit/formcmds.c | 20 | ||||
-rw-r--r-- | libpurple/protocols/mxit/http.c | 6 | ||||
-rw-r--r-- | libpurple/protocols/mxit/markup.c | 19 | ||||
-rw-r--r-- | libpurple/protocols/mxit/protocol.c | 212 | ||||
-rw-r--r-- | libpurple/protocols/mxit/protocol.h | 8 | ||||
-rw-r--r-- | libpurple/protocols/mxit/splashscreen.c | 6 | ||||
-rw-r--r-- | libpurple/protocols/mxit/splashscreen.h | 2 |
13 files changed, 372 insertions, 282 deletions
@@ -14,6 +14,23 @@ version 2.10.13 (MM/DD/YY): * 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) + * Fixed an invalid read. Discovered by Yves Younan of Cisco Talos + (TALOS-CAN-0118) + * Fixed a remote buffer overflow vulnerability. Discovered by Yves + Younan of Cisco Talos. (TALOS-CAN-0119) + * Fixed an out-of-bounds read discovered by Yves Younan of Cisco Talos. + (TALOS-CAN-0123) + * Fixed a directory traversal issue. Discovered by Yves Younan of Cisco + Talos (TALOS-CAN-0128) + * Fixed a remote denial of service vulnerability that could result in + a null pointer dereference. Discovered by Yves Younan of Cisco Talos. + (TALOS-CAN-0133) * Fixed a remote denial of service that could result in an out-of-bounds read. Discovered by Yves Younan of Cisco Talos (TALOS-CAN-0134) diff --git a/libpurple/plugins/ssl/ssl-gnutls.c b/libpurple/plugins/ssl/ssl-gnutls.c index 063ee69c53..e8306dd120 100644 --- a/libpurple/plugins/ssl/ssl-gnutls.c +++ b/libpurple/plugins/ssl/ssl-gnutls.c @@ -608,7 +608,7 @@ ssl_gnutls_get_peer_certificates(PurpleSslConnection * gsc) TODO: Is anyone complaining? (Maybe elb?) */ /* only append if previous cert was actually signed by this one. * Thanks Microsoft. */ - if ((prvcrt == NULL) || x509_certificate_signed_by(prvcrt, newcrt)) { + if ((newcrt != NULL) && ((prvcrt == NULL) || x509_certificate_signed_by(prvcrt, newcrt))) { peer_certs = g_list_append(peer_certs, newcrt); prvcrt = newcrt; } else { @@ -685,12 +685,18 @@ x509_import_from_datum(const gnutls_datum_t dt, gnutls_x509_crt_fmt_t mode) /* Allocate and prepare the internal certificate data */ certdat = g_new0(x509_crtdata_t, 1); - gnutls_x509_crt_init(&(certdat->crt)); + if (gnutls_x509_crt_init(&(certdat->crt)) != 0) { + g_free(certdat); + return NULL; + } certdat->refcount = 0; /* Perform the actual certificate parse */ /* Yes, certdat->crt should be passed as-is */ - gnutls_x509_crt_import(certdat->crt, &dt, mode); + if (gnutls_x509_crt_import(certdat->crt, &dt, mode) != 0) { + g_free(certdat); + return NULL; + } /* Allocate the certificate and load it with data */ crt = g_new0(PurpleCertificate, 1); @@ -780,7 +786,9 @@ x509_importcerts_from_file(const gchar * filename) /* Perform the conversion; files should be in PEM format */ crt = x509_import_from_datum(dt, GNUTLS_X509_FMT_PEM); - crts = g_slist_prepend(crts, crt); + if (crt != NULL) { + crts = g_slist_prepend(crts, crt); + } begin = end; } diff --git a/libpurple/protocols/mxit/chunk.c b/libpurple/protocols/mxit/chunk.c index a575bcdd75..66dbb3a6b7 100644 --- a/libpurple/protocols/mxit/chunk.c +++ b/libpurple/protocols/mxit/chunk.c @@ -151,11 +151,15 @@ static int add_utf8_string( char* chunkdata, const char* str ) * 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* chunkdata, char* value ) * 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* chunkdata, short* value ) * 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* chunkdata, int* value ) * 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* chunkdata, int64_t* value ) * 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* chunkdata, char* dest, int datalen ) * 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* chunkdata, char* str, int maxstrlen ) } /* 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* chunkdata, char* str, int maxstrlen ) * @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* chunkdata, const char* fileid ) * @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* chunkdata, const char* fileid, int filesize, in * @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* chunkdata, const char* fileid, unsigned 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* chunkdata, const char* username, const c * @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* chunkdata, const unsigned char* data, in * @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* chunkdata, const char* mxitId, const cha * @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* chunkdata, int datalen, struct offerfile_chun /* flags [4 bytes] */ /* not used by libPurple */ + + return TRUE; } @@ -492,27 +522,41 @@ void mxit_chunk_parse_offer( char* chunkdata, int datalen, struct offerfile_chun * @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] */ - pos += get_int32( &chunkdata[pos], &(getfile->length) ); + pos += get_int32( &chunkdata[pos], datalen - pos, &(getfile->length) ); /* crc [4 bytes] */ - pos += get_int32( &chunkdata[pos], &(getfile->crc) ); + pos += get_int32( &chunkdata[pos], datalen - pos, &(getfile->crc) ); + + /* check length does not exceed chunked data length */ + if ( getfile->length > datalen - pos ) + return FALSE; /* file data */ - getfile->data = &chunkdata[pos]; + if ( getfile->length > 0 ) + getfile->data = &chunkdata[pos]; + + return TRUE; } @@ -522,27 +566,37 @@ void mxit_chunk_parse_get( char* chunkdata, int datalen, struct getfile_chunk* g * @param chunkdata Chunked data buffer * @param datalen The length of the chunked data * @param splash Decoded splash image information + * @return TRUE if successfully parsed, otherwise FALSE */ -static void mxit_chunk_parse_splash( char* chunkdata, int datalen, struct splash_chunk* splash ) +gboolean mxit_chunk_parse_splash( char* chunkdata, size_t datalen, struct splash_chunk* splash ) { - int pos = 0; + size_t pos = 0; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_splash (%zu bytes)\n", datalen ); - purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_splash (%i bytes)\n", datalen ); + memset( splash, 0, sizeof( struct splash_chunk ) ); + + /* ensure that the chunk size is atleast the minimum size for a "splash screen" chunk */ + if ( datalen < 6 ) + return FALSE; /* anchor [1 byte] */ - pos += get_int8( &chunkdata[pos], &(splash->anchor) ); + pos += get_int8( &chunkdata[pos], datalen - pos, &(splash->anchor) ); /* time to show [1 byte] */ - pos += get_int8( &chunkdata[pos], &(splash->showtime) ); + pos += get_int8( &chunkdata[pos], datalen - pos, &(splash->showtime) ); /* background color [4 bytes] */ - pos += get_int32( &chunkdata[pos], &(splash->bgcolor) ); + pos += get_int32( &chunkdata[pos], datalen - pos, &(splash->bgcolor) ); /* file data */ - splash->data = &chunkdata[pos]; + if ( pos < datalen ) + splash->data = &chunkdata[pos]; /* data length */ splash->datalen = datalen - pos; + + return TRUE; } @@ -552,41 +606,51 @@ static void mxit_chunk_parse_splash( char* chunkdata, int datalen, struct splash * @param chunkdata Chunked data buffer * @param datalen The length of the chunked data * @param offer Decoded custom resource + * @return TRUE if successfully parsed, otherwise FALSE */ -void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr ) +gboolean mxit_chunk_parse_cr( char* chunkdata, size_t datalen, struct cr_chunk* cr ) { - int pos = 0; - int chunklen = 0; + size_t pos = 0; + unsigned int chunkslen = 0; - purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_cr (%i bytes)\n", datalen ); + purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_cr (%zu bytes)\n", datalen ); + + memset( cr, 0, sizeof( struct cr_chunk ) ); /* id [UTF-8] */ - pos += get_utf8_string( &chunkdata[pos], cr->id, sizeof( cr->id ) ); + pos += get_utf8_string( &chunkdata[pos], datalen - pos, cr->id, sizeof( cr->id ) ); /* handle [UTF-8] */ - pos += get_utf8_string( &chunkdata[pos], cr->handle, sizeof( cr->handle ) ); + pos += get_utf8_string( &chunkdata[pos], datalen - pos, cr->handle, sizeof( cr->handle ) ); /* operation [1 byte] */ - pos += get_int8( &chunkdata[pos], &(cr->operation) ); + pos += get_int8( &chunkdata[pos], datalen - pos, &(cr->operation) ); + + /* total length of all the chunks that are included [4 bytes] */ + pos += get_int32( &chunkdata[pos], datalen - pos, &chunkslen ); - /* chunk size [4 bytes] */ - pos += get_int32( &chunkdata[pos], &chunklen ); + /* ensure the chunks size does not exceed the data size */ + if ( pos + chunkslen > datalen ) + return FALSE; /* parse the resource chunks */ - while ( chunklen > 0 ) { - gchar* chunk = &chunkdata[pos]; + while ( chunkslen >= MXIT_CHUNK_HEADER_SIZE ) { + gchar* chunk = &chunkdata[pos]; + guint32 chunksize = chunk_length( chunk ); - /* start of chunk data */ - pos += MXIT_CHUNK_HEADER_SIZE; + /* check chunk size against length of received data */ + if ( pos + MXIT_CHUNK_HEADER_SIZE + chunksize > datalen ) + return FALSE; switch ( chunk_type( chunk ) ) { case CP_CHUNK_SPLASH : /* splash image */ { struct splash_chunk* splash = g_new0( struct splash_chunk, 1 ); - mxit_chunk_parse_splash( &chunkdata[pos], chunk_length( chunk ), splash ); - - cr->resources = g_list_append( cr->resources, splash ); + if ( mxit_chunk_parse_splash( chunk_data( chunk ), chunksize, splash ) ) + cr->resources = g_list_append( cr->resources, splash ); + else + g_free( splash ); break; } case CP_CHUNK_CLICK : /* splash click */ @@ -601,9 +665,11 @@ void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr ) } /* skip over data to next resource chunk */ - pos += chunk_length( chunk ); - chunklen -= ( MXIT_CHUNK_HEADER_SIZE + chunk_length( chunk ) ); + pos += MXIT_CHUNK_HEADER_SIZE + chunksize; + chunkslen -= ( MXIT_CHUNK_HEADER_SIZE + chunksize ); } + + return TRUE; } @@ -613,28 +679,33 @@ void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr ) * @param chunkdata Chunked data buffer * @param datalen The length of the chunked data * @param sendfile Decoded sendfile information + * @return TRUE if successfully parsed, otherwise FALSE */ -void mxit_chunk_parse_sendfile( char* chunkdata, int datalen, struct sendfile_chunk* sendfile ) +gboolean mxit_chunk_parse_sendfile( char* chunkdata, size_t datalen, struct sendfile_chunk* sendfile ) { - int pos = 0; - short entries = 0; + size_t pos = 0; + unsigned short entries = 0; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_sendfile (%zu bytes)\n", datalen ); - purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_sendfile (%i bytes)\n", datalen ); + memset( sendfile, 0, sizeof( struct sendfile_chunk ) ); /* number of entries [2 bytes] */ - pos += get_int16( &chunkdata[pos], &entries ); + pos += get_int16( &chunkdata[pos], datalen - pos, &entries ); if ( entries < 1 ) /* no data */ - return; + return FALSE; /* contactAddress [UTF-8 string] */ - pos += get_utf8_string( &chunkdata[pos], sendfile->username, sizeof( sendfile->username ) ); + pos += get_utf8_string( &chunkdata[pos], datalen - pos, sendfile->username, sizeof( sendfile->username ) ); /* status [4 bytes] */ - pos += get_int32( &chunkdata[pos], &(sendfile->status) ); + pos += get_int32( &chunkdata[pos], datalen - pos, &(sendfile->status) ); /* status message [UTF-8 string] */ - pos += get_utf8_string( &chunkdata[pos], sendfile->statusmsg, sizeof( sendfile->statusmsg ) ); + pos += get_utf8_string( &chunkdata[pos], datalen - pos, sendfile->statusmsg, sizeof( sendfile->statusmsg ) ); + + return TRUE; } @@ -644,44 +715,54 @@ void mxit_chunk_parse_sendfile( char* chunkdata, int datalen, struct sendfile_ch * @param chunkdata Chunked data buffer * @param datalen The length of the chunked data * @param avatar Decoded avatar information + * @return TRUE if successfully parsed, otherwise FALSE */ -void mxit_chunk_parse_get_avatar( char* chunkdata, int datalen, struct getavatar_chunk* avatar ) +gboolean mxit_chunk_parse_get_avatar( char* chunkdata, size_t datalen, struct getavatar_chunk* avatar ) { - int pos = 0; - int numfiles = 0; + size_t pos = 0; + unsigned int numfiles = 0; - purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_get_avatar (%i bytes)\n", datalen ); + purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_get_avatar (%zu bytes)\n", datalen ); + + memset( avatar, 0, sizeof( struct getavatar_chunk ) ); /* number of files [4 bytes] */ - pos += get_int32( &chunkdata[pos], &numfiles ); + pos += get_int32( &chunkdata[pos], datalen - pos, &numfiles ); if ( numfiles < 1 ) /* no data */ - return; + return FALSE; /* mxitId [UTF-8 string] */ - pos += get_utf8_string( &chunkdata[pos], avatar->mxitid, sizeof( avatar->mxitid ) ); + pos += get_utf8_string( &chunkdata[pos], datalen - pos, avatar->mxitid, sizeof( avatar->mxitid ) ); /* avatar id [UTF-8 string] */ - pos += get_utf8_string( &chunkdata[pos], avatar->avatarid, sizeof( avatar->avatarid ) ); + pos += get_utf8_string( &chunkdata[pos], datalen - pos, avatar->avatarid, sizeof( avatar->avatarid ) ); /* format [UTF-8 string] */ - pos += get_utf8_string( &chunkdata[pos], avatar->format, sizeof( avatar->format ) ); + pos += get_utf8_string( &chunkdata[pos], datalen - pos, avatar->format, sizeof( avatar->format ) ); /* bit depth [1 byte] */ - pos += get_int8( &chunkdata[pos], &(avatar->bitdepth) ); + pos += get_int8( &chunkdata[pos], datalen - pos, &(avatar->bitdepth) ); /* crc [4 bytes] */ - pos += get_int32( &chunkdata[pos], &(avatar->crc) ); + pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->crc) ); /* width [4 bytes] */ - pos += get_int32( &chunkdata[pos], &(avatar->width) ); + pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->width) ); /* height [4 bytes] */ - pos += get_int32( &chunkdata[pos], &(avatar->height) ); + pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->height) ); /* file length [4 bytes] */ - pos += get_int32( &chunkdata[pos], &(avatar->length) ); + pos += get_int32( &chunkdata[pos], datalen - pos, &(avatar->length) ); + + /* check length does not exceed chunked data length */ + if ( avatar->length > datalen - pos ) + return FALSE; /* file data */ - avatar->data = &chunkdata[pos]; + if ( avatar->length > 0 ) + avatar->data = &chunkdata[pos]; + + return TRUE; } diff --git a/libpurple/protocols/mxit/chunk.h b/libpurple/protocols/mxit/chunk.h index 6ef094f638..841c4e6172 100644 --- a/libpurple/protocols/mxit/chunk.h +++ b/libpurple/protocols/mxit/chunk.h @@ -85,7 +85,7 @@ static inline void set_chunk_type( gchar* chunkheader, guint type ) static inline guint32 chunk_length( gchar* chunkheader ) { guint32 length = *( (const guint32*) &chunkheader[1] ); - return htonl( length ); + return ntohl( length ); } static inline void set_chunk_length( gchar* chunkheader, guint32 size ) @@ -103,22 +103,22 @@ static inline gchar* chunk_data( gchar* chunkheader ) * Offer File chunk (6). */ struct offerfile_chunk { - char fileid[MXIT_CHUNK_FILEID_LEN]; - char username[MXIT_CP_MAX_JID_LEN + 1]; - int filesize; - char filename[FILENAME_MAX]; - char mimetype[64]; + char fileid[MXIT_CHUNK_FILEID_LEN]; + char username[MXIT_CP_MAX_JID_LEN + 1]; + unsigned int filesize; + char filename[FILENAME_MAX]; + char mimetype[64]; }; /* * Get File chunk (8) response. */ struct getfile_chunk { - char fileid[MXIT_CHUNK_FILEID_LEN]; - int offset; - int length; - int crc; - char* data; + char fileid[MXIT_CHUNK_FILEID_LEN]; + unsigned int offset; + unsigned int length; + unsigned int crc; + char* data; }; /* @@ -135,11 +135,11 @@ struct cr_chunk { * Splash Image chunk (2) */ struct splash_chunk { - char anchor; - char showtime; - int bgcolor; - char* data; - int datalen; + char anchor; + char showtime; + unsigned int bgcolor; + char* data; + unsigned int datalen; }; /* @@ -153,40 +153,41 @@ struct splash_click_chunk { * Get Avatar chunk (14) response. */ struct getavatar_chunk { - char mxitid[50]; - char avatarid[64]; - char format[16]; - char bitdepth; - int crc; - int width; - int height; - int length; - char* data; + char mxitid[50]; + char avatarid[64]; + char format[16]; + char bitdepth; + unsigned int crc; + unsigned int width; + unsigned int height; + unsigned int length; + char* data; }; /* * Send File Direct chunk (10) response. */ struct sendfile_chunk { - char username[MXIT_CP_MAX_JID_LEN + 1]; - int status; - char statusmsg[1024]; + char username[MXIT_CP_MAX_JID_LEN + 1]; + unsigned int status; + char statusmsg[1024]; }; /* Encode chunk */ -int mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, int datalen ); -int mxit_chunk_create_reject( char* chunkdata, const char* fileid ); -int mxit_chunk_create_get( char* chunkdata, const char* fileid, int filesize, int offset ); -int mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status ); -int mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, int datalen ); -int mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId ); +size_t mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, size_t datalen ); +size_t mxit_chunk_create_reject( char* chunkdata, const char* fileid ); +size_t mxit_chunk_create_get( char* chunkdata, const char* fileid, size_t filesize, size_t offset ); +size_t mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status ); +size_t mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, size_t datalen ); +size_t mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId ); /* Decode chunk */ -void mxit_chunk_parse_offer( char* chunkdata, int datalen, struct offerfile_chunk* offer ); -void mxit_chunk_parse_get( char* chunkdata, int datalen, struct getfile_chunk* getfile ); -void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr ); -void mxit_chunk_parse_sendfile( char* chunkdata, int datalen, struct sendfile_chunk* sendfile ); -void mxit_chunk_parse_get_avatar( char* chunkdata, int datalen, struct getavatar_chunk* avatar ); +gboolean mxit_chunk_parse_offer( char* chunkdata, size_t datalen, struct offerfile_chunk* offer ); +gboolean mxit_chunk_parse_get( char* chunkdata, size_t datalen, struct getfile_chunk* getfile ); +gboolean mxit_chunk_parse_cr( char* chunkdata, size_t datalen, struct cr_chunk* cr ); +gboolean mxit_chunk_parse_sendfile( char* chunkdata, size_t datalen, struct sendfile_chunk* sendfile ); +gboolean mxit_chunk_parse_get_avatar( char* chunkdata, size_t datalen, struct getavatar_chunk* avatar ); +gboolean mxit_chunk_parse_splash( char* chunkdata, size_t datalen, struct splash_chunk* splash ); #endif /* _MXIT_CHUNK_H_ */ diff --git a/libpurple/protocols/mxit/filexfer.c b/libpurple/protocols/mxit/filexfer.c index 5eef9cb140..b96f3f08e4 100644 --- a/libpurple/protocols/mxit/filexfer.c +++ b/libpurple/protocols/mxit/filexfer.c @@ -357,7 +357,7 @@ void mxit_xfer_tx( PurpleConnection* gc, const char* who, const char* filename ) * @param filesize The size of the file being offered * @param fileid A unique ID that identifies this file */ -void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, int filesize, const char* fileid ) +void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, unsigned int filesize, const char* fileid ) { PurpleXfer* xfer = NULL; struct mxitxfer* mx = NULL; @@ -373,7 +373,7 @@ void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, cons xfer->data = mx; purple_xfer_set_filename( xfer, filename ); - if( filesize > 0 ) + if ( filesize > 0 ) purple_xfer_set_size( xfer, filesize ); /* register file transfer callback functions */ @@ -429,7 +429,7 @@ static PurpleXfer* find_mxit_xfer( struct MXitSession* session, const char* file * @param data The file data * @param datalen The size of the data */ -void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen ) +void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, unsigned int datalen ) { PurpleXfer* xfer = NULL; diff --git a/libpurple/protocols/mxit/filexfer.h b/libpurple/protocols/mxit/filexfer.h index 4ec953d928..cd0a20f58e 100644 --- a/libpurple/protocols/mxit/filexfer.h +++ b/libpurple/protocols/mxit/filexfer.h @@ -43,8 +43,8 @@ void mxit_xfer_tx( PurpleConnection* gc, const char* who, const char* filename ) PurpleXfer* mxit_xfer_new( PurpleConnection* gc, const char* who ); /* MXit Protocol callbacks */ -void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, int filesize, const char* fileid ); -void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen ); +void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, unsigned int filesize, const char* fileid ); +void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, unsigned int datalen ); #endif /* _MXIT_FILEXFER_H_ */ diff --git a/libpurple/protocols/mxit/formcmds.c b/libpurple/protocols/mxit/formcmds.c index 435a01f76d..1edad2d185 100644 --- a/libpurple/protocols/mxit/formcmds.c +++ b/libpurple/protocols/mxit/formcmds.c @@ -395,6 +395,9 @@ static void command_imagestrip(struct MXitSession* session, const char* from, GH /* validator */ validator = g_hash_table_lookup(hash, "v"); + if (!name || !validator) + return; + /* image data */ tmp = g_hash_table_lookup(hash, "dat"); if (tmp) { @@ -430,13 +433,13 @@ static void command_imagestrip(struct MXitSession* session, const char* from, GH } tmp = g_hash_table_lookup(hash, "fw"); - width = atoi(tmp); + width = (tmp ? atoi(tmp) : 0); tmp = g_hash_table_lookup(hash, "fh"); - height = atoi(tmp); + height = (tmp ? atoi(tmp) : 0); tmp = g_hash_table_lookup(hash, "layer"); - layer = atoi(tmp); + layer = (tmp ? atoi(tmp) : 0); purple_debug_info(MXIT_PLUGIN_ID, "ImageStrip %s from %s: [w=%i h=%i l=%i validator=%s]\n", name, from, width, height, layer, validator); } @@ -525,21 +528,26 @@ static void command_table(struct RXMsgData* mx, GHashTable* hash) /* table name */ name = g_hash_table_lookup(hash, "nm"); + if (!name) + return; /* number of columns */ tmp = g_hash_table_lookup(hash, "col"); - nr_columns = atoi(tmp); + nr_columns = (tmp ? atoi(tmp) : 0); /* number of rows */ tmp = g_hash_table_lookup(hash, "row"); - nr_rows = atoi(tmp); + nr_rows = (tmp ? atoi(tmp) : 0); /* mode */ tmp = g_hash_table_lookup(hash, "mode"); - mode = atoi(tmp); + mode = (tmp ? atoi(tmp) : 0); /* table data */ tmp = g_hash_table_lookup(hash, "d"); + if (!tmp) + tmp = ""; + coldata = g_strsplit(tmp, "~", 0); /* split into entries for each row & column */ if (g_strv_length(coldata) != (nr_rows * nr_columns)) { diff --git a/libpurple/protocols/mxit/http.c b/libpurple/protocols/mxit/http.c index 9a91775366..7631430532 100644 --- a/libpurple/protocols/mxit/http.c +++ b/libpurple/protocols/mxit/http.c @@ -97,9 +97,9 @@ static void mxit_cb_http_read( gpointer user_data, gint source, PurpleInputCondi { struct MXitSession* session = (struct MXitSession*) user_data; char buf[256]; - int buflen; + unsigned int buflen; char* body; - int bodylen; + unsigned int bodylen; char* ch; int len; char* tmp; @@ -182,7 +182,7 @@ nextpacket: goto done; } tmp = g_strndup( ch, tmp - ch ); - bodylen = atoi( tmp ); + bodylen = strtoul( tmp, NULL, 10 ); g_free( tmp ); tmp = NULL; diff --git a/libpurple/protocols/mxit/markup.c b/libpurple/protocols/mxit/markup.c index 92d8d67a16..040927f359 100644 --- a/libpurple/protocols/mxit/markup.c +++ b/libpurple/protocols/mxit/markup.c @@ -1083,7 +1083,6 @@ char* mxit_convert_markup_tx( const char* message, int* msgtype ) GList* entry; GList* tagstack = NULL; char* reply; - char color[8]; int len = strlen ( message ); int i; @@ -1145,12 +1144,18 @@ char* mxit_convert_markup_tx( const char* message, int* msgtype ) } else if ( purple_str_has_prefix( &message[i], "<font color=" ) ) { /* font colour */ - tag = g_new0( struct tag, 1 ); - tag->type = MXIT_TAG_COLOR; - tagstack = g_list_append( tagstack, tag ); - memset( color, 0x00, sizeof( color ) ); - memcpy( color, &message[i + 13], 7 ); - g_string_append( mx, color ); + char color[8]; + + /* ensure we have the complete tag: <font color="#123456"> */ + if ( i + 20 < len ) { + tag = g_new0( struct tag, 1 ); + tag->type = MXIT_TAG_COLOR; + tagstack = g_list_append( tagstack, tag ); + + memset( color, 0x00, sizeof( color ) ); + memcpy( color, &message[i + 13], 7 ); + g_string_append( mx, color ); + } } else if ( purple_str_has_prefix( &message[i], "</font>" ) ) { /* end of font tag */ diff --git a/libpurple/protocols/mxit/protocol.c b/libpurple/protocols/mxit/protocol.c index 235e13abec..fb127f390d 100644 --- a/libpurple/protocols/mxit/protocol.c +++ b/libpurple/protocols/mxit/protocol.c @@ -1223,14 +1223,14 @@ void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid * @param buf The content of the file * @param buflen The length of the file contents */ -void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen ) +void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, size_t buflen ) { char data[CP_MAX_PACKET]; int datalen = 0; gchar* chunk; - int size; + size_t chunksize; - purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %i bytes to user '%s'\n", filename, buflen, username ); + purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %zu bytes to user '%s'\n", filename, buflen, username ); /* convert the packet to a byte stream */ datalen = g_snprintf( data, sizeof( data ), "ms=" ); @@ -1238,15 +1238,11 @@ void mxit_send_file( struct MXitSession* session, const char* username, const ch /* map chunk header over data buffer */ chunk = &data[datalen]; - size = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen ); - if ( size < 0 ) { - purple_debug_error( MXIT_PLUGIN_ID, "Error creating senddirect chunk (%i)\n", size ); - return; - } - + /* encode chunk */ + chunksize = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen ); set_chunk_type( chunk, CP_CHUNK_DIRECT_SND ); - set_chunk_length( chunk, size ); - datalen += MXIT_CHUNK_HEADER_SIZE + size; + set_chunk_length( chunk, chunksize ); + datalen += MXIT_CHUNK_HEADER_SIZE + chunksize; /* send the byte stream to the mxit server */ mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); @@ -1264,7 +1260,7 @@ void mxit_send_file_reject( struct MXitSession* session, const char* fileid ) char data[CP_MAX_PACKET]; int datalen = 0; gchar* chunk; - int size; + size_t chunksize; purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" ); @@ -1274,15 +1270,11 @@ void mxit_send_file_reject( struct MXitSession* session, const char* fileid ) /* map chunk header over data buffer */ chunk = &data[datalen]; - size = mxit_chunk_create_reject( chunk_data( chunk ), fileid ); - if ( size < 0 ) { - purple_debug_error( MXIT_PLUGIN_ID, "Error creating reject chunk (%i)\n", size ); - return; - } - + /* encode chunk */ + chunksize = mxit_chunk_create_reject( chunk_data( chunk ), fileid ); set_chunk_type( chunk, CP_CHUNK_REJECT ); - set_chunk_length( chunk, size ); - datalen += MXIT_CHUNK_HEADER_SIZE + size; + set_chunk_length( chunk, chunksize ); + datalen += MXIT_CHUNK_HEADER_SIZE + chunksize; /* send the byte stream to the mxit server */ mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); @@ -1297,12 +1289,12 @@ void mxit_send_file_reject( struct MXitSession* session, const char* fileid ) * @param filesize The number of bytes to retrieve * @param offset Offset in file at which to start retrieving */ -void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset ) +void mxit_send_file_accept( struct MXitSession* session, const char* fileid, size_t filesize, size_t offset ) { char data[CP_MAX_PACKET]; int datalen = 0; gchar* chunk; - int size; + size_t chunksize; purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" ); @@ -1312,15 +1304,11 @@ void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int /* map chunk header over data buffer */ chunk = &data[datalen]; - size = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset ); - if ( size < 0 ) { - purple_debug_error( MXIT_PLUGIN_ID, "Error creating getfile chunk (%i)\n", size ); - return; - } - + /* encode chunk */ + chunksize = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset ); set_chunk_type( chunk, CP_CHUNK_GET ); - set_chunk_length( chunk, size ); - datalen += MXIT_CHUNK_HEADER_SIZE + size; + set_chunk_length( chunk, chunksize ); + datalen += MXIT_CHUNK_HEADER_SIZE + chunksize; /* send the byte stream to the mxit server */ mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); @@ -1338,7 +1326,7 @@ void mxit_send_file_received( struct MXitSession* session, const char* fileid, s char data[CP_MAX_PACKET]; int datalen = 0; gchar* chunk; - int size; + size_t chunksize; purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" ); @@ -1348,15 +1336,11 @@ void mxit_send_file_received( struct MXitSession* session, const char* fileid, s /* map chunk header over data buffer */ chunk = &data[datalen]; - size = mxit_chunk_create_received( chunk_data(chunk), fileid, status ); - if ( size < 0 ) { - purple_debug_error( MXIT_PLUGIN_ID, "Error creating received chunk (%i)\n", size ); - return; - } - + /* encode chunk */ + chunksize = mxit_chunk_create_received( chunk_data(chunk), fileid, status ); set_chunk_type( chunk, CP_CHUNK_RECEIVED ); - set_chunk_length( chunk, size ); - datalen += MXIT_CHUNK_HEADER_SIZE + size; + set_chunk_length( chunk, chunksize ); + datalen += MXIT_CHUNK_HEADER_SIZE + chunksize; /* send the byte stream to the mxit server */ mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); @@ -1370,14 +1354,14 @@ void mxit_send_file_received( struct MXitSession* session, const char* fileid, s * @param data The avatar data * @param buflen The length of the avatar data */ -void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen ) +void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, size_t avatarlen ) { char data[CP_MAX_PACKET]; int datalen = 0; gchar* chunk; - int size; + size_t chunksize; - purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %i bytes\n", avatarlen ); + purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %zu bytes\n", avatarlen ); /* convert the packet to a byte stream */ datalen = g_snprintf( data, sizeof( data ), "ms=" ); @@ -1385,15 +1369,11 @@ void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, /* map chunk header over data buffer */ chunk = &data[datalen]; - size = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen ); - if ( size < 0 ) { - purple_debug_error( MXIT_PLUGIN_ID, "Error creating set avatar chunk (%i)\n", size ); - return; - } - + /* encode chunk */ + chunksize = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen ); set_chunk_type( chunk, CP_CHUNK_SET_AVATAR ); - set_chunk_length( chunk, size ); - datalen += MXIT_CHUNK_HEADER_SIZE + size; + set_chunk_length( chunk, chunksize ); + datalen += MXIT_CHUNK_HEADER_SIZE + chunksize; /* send the byte stream to the mxit server */ mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); @@ -1414,7 +1394,7 @@ void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const cha char data[CP_MAX_PACKET]; int datalen = 0; gchar* chunk; - int size; + size_t chunksize; purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId ); @@ -1424,15 +1404,11 @@ void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const cha /* map chunk header over data buffer */ chunk = &data[datalen]; - size = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId ); - if ( size < 0 ) { - purple_debug_error( MXIT_PLUGIN_ID, "Error creating get avatar chunk (%i)\n", size ); - return; - } - + /* encode chunk */ + chunksize = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId ); set_chunk_type( chunk, CP_CHUNK_GET_AVATAR ); - set_chunk_length( chunk, size ); - datalen += MXIT_CHUNK_HEADER_SIZE + size; + set_chunk_length( chunk, chunksize ); + datalen += MXIT_CHUNK_HEADER_SIZE + chunksize; /* send the byte stream to the mxit server */ mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA ); @@ -2100,21 +2076,6 @@ static void mxit_parse_cmd_msgevent( struct MXitSession* session, struct record* /*------------------------------------------------------------------------ - * Return the length of a multimedia chunk - * - * @return The actual chunk data length in bytes - */ -static int get_chunk_len( const char* chunkdata ) -{ - int* sizeptr; - - sizeptr = (int*) &chunkdata[1]; /* we skip the first byte (type field) */ - - return ntohl( *sizeptr ); -} - - -/*------------------------------------------------------------------------ * Process a received multimedia packet. * * @param session The MXit session object @@ -2123,42 +2084,52 @@ static int get_chunk_len( const char* chunkdata ) */ static void mxit_parse_cmd_media( struct MXitSession* session, struct record** records, int rcount ) { - char type; - int size; + guint chunktype; + guint32 chunksize; + gchar* chunkdata; - type = records[0]->fields[0]->data[0]; - size = get_chunk_len( records[0]->fields[0]->data ); + /* received packet is too short to even contain a chunk header */ + if ( records[0]->fields[0]->len < MXIT_CHUNK_HEADER_SIZE ) + return; - purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i bytes)\n", rcount, size ); + /* decode the chunk header */ + chunktype = chunk_type( records[0]->fields[0]->data ); + chunksize = chunk_length( records[0]->fields[0]->data ); + chunkdata = chunk_data( records[0]->fields[0]->data ); + + /* check chunk size against length of received data */ + if ( MXIT_CHUNK_HEADER_SIZE + chunksize > records[0]->fields[0]->len ) + return; + + purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i type) (%i bytes)\n", rcount, chunktype, chunksize ); /* supported chunked data types */ - switch ( type ) { + switch ( chunktype ) { case CP_CHUNK_CUSTOM : /* custom resource */ { struct cr_chunk chunk; /* decode the chunked data */ - memset( &chunk, 0, sizeof( struct cr_chunk ) ); - mxit_chunk_parse_cr( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); + if ( mxit_chunk_parse_cr( chunkdata, chunksize, &chunk ) ) { - purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation ); + purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation ); - /* this is a splash-screen operation */ - if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) { - if ( chunk.operation == CR_OP_UPDATE ) { /* update the splash-screen */ - struct splash_chunk *splash = chunk.resources->data; // TODO: Fix - assuming 1st resource is splash - gboolean clickable = ( g_list_length( chunk.resources ) > 1 ); // TODO: Fix - if 2 resources, then is clickable + /* this is a splash-screen operation */ + if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) { + if ( chunk.operation == CR_OP_UPDATE ) { /* update the splash-screen */ + struct splash_chunk *splash = chunk.resources->data; // TODO: Fix - assuming 1st resource is splash + gboolean clickable = ( g_list_length( chunk.resources ) > 1 ); // TODO: Fix - if 2 resources, then is clickable - if ( splash != NULL ) - splash_update( session, chunk.id, splash->data, splash->datalen, clickable ); + if ( splash != NULL ) + splash_update( session, chunk.id, splash->data, splash->datalen, clickable ); + } + else if ( chunk.operation == CR_OP_REMOVE ) /* remove the splash-screen */ + splash_remove( session ); } - else if ( chunk.operation == CR_OP_REMOVE ) /* remove the splash-screen */ - splash_remove( session ); - } - - /* cleanup custom resources */ - g_list_foreach( chunk.resources, (GFunc)g_free, NULL ); + /* cleanup custom resources */ + g_list_foreach( chunk.resources, (GFunc)g_free, NULL ); + } } break; @@ -2167,11 +2138,10 @@ static void mxit_parse_cmd_media( struct MXitSession* session, struct record** r struct offerfile_chunk chunk; /* decode the chunked data */ - memset( &chunk, 0, sizeof( struct offerfile_chunk ) ); - mxit_chunk_parse_offer( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); - - /* process the offer */ - mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid ); + if ( mxit_chunk_parse_offer( chunkdata, chunksize, &chunk ) ) { + /* process the offer */ + mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid ); + } } break; @@ -2180,11 +2150,10 @@ static void mxit_parse_cmd_media( struct MXitSession* session, struct record** r struct getfile_chunk chunk; /* decode the chunked data */ - memset( &chunk, 0, sizeof( struct getfile_chunk ) ); - mxit_chunk_parse_get( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); - - /* process the getfile */ - mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length ); + if ( mxit_chunk_parse_get( chunkdata, chunksize, &chunk ) ) { + /* process the getfile */ + mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length ); + } } break; @@ -2194,11 +2163,8 @@ static void mxit_parse_cmd_media( struct MXitSession* session, struct record** r struct contact* contact = NULL; /* decode the chunked data */ - memset( &chunk, 0, sizeof( struct getavatar_chunk ) ); - mxit_chunk_parse_get_avatar( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); - - /* update avatar image */ - if ( chunk.data ) { + if ( mxit_chunk_parse_get_avatar( chunkdata, chunksize, &chunk ) ) { + /* update avatar image */ purple_debug_info( MXIT_PLUGIN_ID, "updating avatar for contact '%s'\n", chunk.mxitid ); contact = get_mxit_invite_contact( session, chunk.mxitid ); @@ -2220,18 +2186,21 @@ static void mxit_parse_cmd_media( struct MXitSession* session, struct record** r /* this is a reply packet to a set avatar request. no action is required */ break; + case CP_CHUNK_REJECT : + /* this is a reply packet to a reject file request. no action is required */ + break; + case CP_CHUNK_DIRECT_SND : /* this is a ack for a file send. */ { struct sendfile_chunk chunk; - memset( &chunk, 0, sizeof( struct sendfile_chunk ) ); - mxit_chunk_parse_sendfile( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk ); - - purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg ); + if ( mxit_chunk_parse_sendfile( chunkdata, chunksize, &chunk ) ) { + purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg ); - if ( chunk.status != 0 ) /* not success */ - mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg ); + if ( chunk.status != 0 ) /* not success */ + mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg ); + } } break; @@ -2240,7 +2209,7 @@ static void mxit_parse_cmd_media( struct MXitSession* session, struct record** r break; default : - purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", type ); + purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", chunktype ); break; } } @@ -2556,7 +2525,7 @@ static void dump_packet( struct rx_packet* p ) for ( j = 0; j < r->fcount; j++ ) { f = r->fields[j]; - purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%i) '%s' \n", f->len, f->data ); + purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%zu) '%s' \n", f->len, f->data ); } } } @@ -2677,7 +2646,7 @@ int mxit_parse_packet( struct MXitSession* session ) field->data = &session->rx_dbuf[i + 1]; field->len = session->rx_i - i; /* now skip the binary data */ - res = get_chunk_len( field->data ); + res = chunk_length( field->data ); /* determine if we have more packets */ if ( res + 6 + i < session->rx_i ) { /* we have more than one packet in this stream */ @@ -2806,8 +2775,9 @@ void mxit_cb_rx( gpointer user_data, gint source, PurpleInputCondition cond ) /* the end of the length record found */ session->rx_lbuf[session->rx_i] = '\0'; session->rx_res = atoi( &session->rx_lbuf[3] ); - if ( session->rx_res > CP_MAX_PACKET ) { + if ( ( session->rx_res <= 0 ) || ( session->rx_res > CP_MAX_PACKET ) ) { purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x03)" ) ); + return; } session->rx_state = RX_STATE_DATA; session->rx_i = 0; diff --git a/libpurple/protocols/mxit/protocol.h b/libpurple/protocols/mxit/protocol.h index 8826f0d05c..fad7ae54c0 100644 --- a/libpurple/protocols/mxit/protocol.h +++ b/libpurple/protocols/mxit/protocol.h @@ -241,7 +241,7 @@ struct MXitSession; struct field { char* data; - int len; + size_t len; }; struct record { @@ -332,11 +332,11 @@ void mxit_send_update_contact( struct MXitSession* session, const char* username void mxit_send_splashclick( struct MXitSession* session, const char* splashid ); void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event); -void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen ); +void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, size_t buflen ); void mxit_send_file_reject( struct MXitSession* session, const char* fileid ); -void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset ); +void mxit_send_file_accept( struct MXitSession* session, const char* fileid, size_t filesize, size_t offset ); void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status ); -void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen ); +void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, size_t avatarlen ); void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId ); void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] ); diff --git a/libpurple/protocols/mxit/splashscreen.c b/libpurple/protocols/mxit/splashscreen.c index 655cfd4879..2732e237a8 100644 --- a/libpurple/protocols/mxit/splashscreen.c +++ b/libpurple/protocols/mxit/splashscreen.c @@ -93,7 +93,7 @@ void splash_remove(struct MXitSession* session) purple_debug_info(MXIT_PLUGIN_ID, "Removing splashId: '%s'\n", splashId); /* Delete stored splash image */ - filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit" G_DIR_SEPARATOR_S "%s.png", purple_user_dir(), splashId); + filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit" G_DIR_SEPARATOR_S "%s.png", purple_user_dir(), purple_escape_filename(splashId)); g_unlink(filename); g_free(filename); @@ -112,7 +112,7 @@ void splash_remove(struct MXitSession* session) * @param data Splash-screen image data (PNG format) * @param datalen Splash-screen image data size */ -void splash_update(struct MXitSession* session, const char* splashId, const char* data, int datalen, gboolean clickable) +void splash_update(struct MXitSession* session, const char* splashId, const char* data, unsigned int datalen, gboolean clickable) { char* dir; char* filename; @@ -179,7 +179,7 @@ void splash_display(struct MXitSession* session) purple_debug_info(MXIT_PLUGIN_ID, "Display Splash: '%s'\n", splashId); /* Load splash-screen image from file */ - filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit" G_DIR_SEPARATOR_S "%s.png", purple_user_dir(), splashId); + filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit" G_DIR_SEPARATOR_S "%s.png", purple_user_dir(), purple_escape_filename(splashId)); if (g_file_get_contents(filename, &imgdata, &imglen, NULL)) { char buf[128]; diff --git a/libpurple/protocols/mxit/splashscreen.h b/libpurple/protocols/mxit/splashscreen.h index eb148d7aba..ddc959c50b 100644 --- a/libpurple/protocols/mxit/splashscreen.h +++ b/libpurple/protocols/mxit/splashscreen.h @@ -44,7 +44,7 @@ gboolean splash_popup_enabled(struct MXitSession* session); /* * Save a new splash-screen. */ -void splash_update(struct MXitSession* session, const char* splashId, const char* data, int datalen, gboolean clickable); +void splash_update(struct MXitSession* session, const char* splashId, const char* data, unsigned int datalen, gboolean clickable); /* * Remove the stored splash-screen (if it exists). |