qulogic/pidgin

Merged TALOS-CAN-0136
release-2.x.y
2016-06-12, Gary Kramlich
89b326ceca25
Merged TALOS-CAN-0136
--- a/ChangeLog Sun Jun 12 22:13:22 2016 -0500
+++ b/ChangeLog Sun Jun 12 22:15:07 2016 -0500
@@ -33,6 +33,8 @@
(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)
+ * Fixed multiple remote buffer overflows. Discovered by Yves Younan of
+ Cisco Talos. (TALOS-CAN-0136)
version 2.10.12 (12/31/15):
General:
--- a/libpurple/protocols/mxit/http.c Sun Jun 12 22:13:22 2016 -0500
+++ b/libpurple/protocols/mxit/http.c Sun Jun 12 22:15:07 2016 -0500
@@ -63,9 +63,9 @@
* @param pktlen The length of the packet data
* @return Return -1 on error, otherwise 0
*/
-static int mxit_http_raw_write( int fd, const char* pktdata, int pktlen )
+static int mxit_http_raw_write( int fd, const char* pktdata, size_t pktlen )
{
- int written;
+ size_t written;
int res;
written = 0;
@@ -315,22 +315,25 @@
* @param session The MXit session object
* @param host The server name to connect to
* @param port The port number to connect to
- * @param data The HTTP request data (including HTTP headers etc.)
+ * @param header The HTTP header.
+ * @param data The HTTP request data.
* @param datalen The HTTP request data length
*/
-void mxit_http_send_request( struct MXitSession* session, char* host, int port, const char* data, int datalen )
+void mxit_http_send_request( struct MXitSession* session, char* host, int port, gchar* header, const char* data, size_t datalen )
{
PurpleProxyConnectData* con = NULL;
struct http_request* req;
+ size_t headerlen = strlen( header );
/* build the http request */
req = g_new0( struct http_request, 1 );
req->session = session;
req->host = host;
req->port = port;
- req->data = g_malloc0( datalen );
- memcpy( req->data, data, datalen );
- req->datalen = datalen;
+ req->data = g_malloc0( headerlen + datalen );
+ memcpy( req->data, header, headerlen );
+ memcpy( req->data + headerlen, data, datalen );
+ req->datalen = headerlen + datalen;
/* open connection to the HTTP server */
con = purple_proxy_connect( NULL, session->acc, host, port, mxit_cb_http_connect, req );
--- a/libpurple/protocols/mxit/http.h Sun Jun 12 22:13:22 2016 -0500
+++ b/libpurple/protocols/mxit/http.h Sun Jun 12 22:15:07 2016 -0500
@@ -35,11 +35,11 @@
char* host;
int port;
char* data;
- int datalen;
+ size_t datalen;
};
-void mxit_http_send_request( struct MXitSession* session, char* host, int port, const char* data, int datalen );
+void mxit_http_send_request( struct MXitSession* session, char* host, int port, gchar* header, const char* data, size_t datalen );
--- a/libpurple/protocols/mxit/protocol.c Sun Jun 12 22:13:22 2016 -0500
+++ b/libpurple/protocols/mxit/protocol.c Sun Jun 12 22:15:07 2016 -0500
@@ -148,6 +148,34 @@
}
+/*------------------------------------------------------------------------
+ * scnprintf
+ *
+ * @param string The destination buffer.
+ * @param size The maximum size of the destination buffer.
+ * @param format The format string
+ * @param ... The parameters to the format string.
+ * @return The number of characters actually stored in the buffer.
+ */
+static int scnprintf( gchar* string, size_t size, const char *format, ... )
+{
+ va_list args;
+ guint i;
+
+ va_start( args, format );
+ i = g_vsnprintf( string, size, format, args );
+ va_end( args );
+
+ if ( i < size )
+ return i;
+ else if ( size > 0 ) /* destination buffer too short - return number of characters actually inserted */
+ return size - 1;
+ else
+ return 0;
+}
+
+
+
/*========================================================================================================================
* Low-level Packet transmission
*/
@@ -334,11 +362,10 @@
*/
static void mxit_write_http_post( struct MXitSession* session, struct tx_packet* packet )
{
- char request[256 + packet->datalen];
- int reqlen;
char* host_name;
int host_port;
gboolean ok;
+ gchar* httpheader;
/* extract the HTTP host name and host port number to connect to */
ok = purple_url_parse( session->http_server, &host_name, &host_port, NULL, NULL, NULL );
@@ -350,8 +377,8 @@
packet->header[packet->headerlen - 1] = '\0';
packet->headerlen--;
- /* build the HTTP request packet */
- reqlen = g_snprintf( request, 256,
+ /* build the HTTP request header */
+ httpheader = g_strdup_printf(
"POST %s?%s HTTP/1.1\r\n"
"User-Agent: " MXIT_HTTP_USERAGENT "\r\n"
"Content-Type: application/octet-stream\r\n"
@@ -364,17 +391,17 @@
packet->datalen - MXIT_MS_OFFSET
);
- /* copy over the packet body data (could be binary) */
- memcpy( request + reqlen, packet->data + MXIT_MS_OFFSET, packet->datalen - MXIT_MS_OFFSET );
- reqlen += packet->datalen;
-
#ifdef DEBUG_PROTOCOL
purple_debug_info( MXIT_PLUGIN_ID, "HTTP POST:\n" );
- dump_bytes( session, request, reqlen );
+ dump_bytes( session, httpheader, strlen( httpheader ) );
+ dump_bytes( session, packet->data + MXIT_MS_OFFSET, packet->datalen - MXIT_MS_OFFSET );
#endif
/* send the request to the HTTP server */
- mxit_http_send_request( session, host_name, host_port, request, reqlen );
+ mxit_http_send_request( session, host_name, host_port, httpheader, packet->data + MXIT_MS_OFFSET, packet->datalen - MXIT_MS_OFFSET );
+
+ /* cleanup */
+ g_free( httpheader );
}
@@ -463,23 +490,23 @@
packet->headerlen = 0;
/* create generic packet header */
- hlen = g_snprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM ); /* client mxitid */
+ hlen = scnprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM ); /* client mxitid */
if ( session->http ) {
/* http connection only */
- hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "s=" );
+ hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "s=" );
if ( session->http_sesid > 0 ) {
- hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_sesid, CP_FLD_TERM ); /* http session id */
+ hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_sesid, CP_FLD_TERM ); /* http session id */
}
session->http_seqno++;
- hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_seqno, CP_REC_TERM ); /* http request sequence id */
+ hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_seqno, CP_REC_TERM ); /* http request sequence id */
}
- hlen += g_snprintf( header + hlen, sizeof( header ) - hlen, "cm=%i%c", cmd, CP_REC_TERM ); /* packet command */
+ hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "cm=%i%c", cmd, CP_REC_TERM ); /* packet command */
if ( !session->http ) {
/* socket connection only */
- packet->headerlen = g_snprintf( packet->header, sizeof( packet->header ), "ln=%i%c", ( datalen + hlen ), CP_REC_TERM ); /* packet length */
+ packet->headerlen = scnprintf( packet->header, sizeof( packet->header ), "ln=%i%c", ( datalen + hlen ), CP_REC_TERM ); /* packet length */
}
/* copy the header to packet */
@@ -710,7 +737,7 @@
clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%s%c%i%c%s%c" /* "ms"=password\1version\1maxreplyLen\1name\1 */
"%s%c%i%c%s%c%s%c" /* dateOfBirth\1gender\1location\1capabilities\1 */
"%s%c%i%c%s%c%s" /* dc\1features\1dialingcode\1locale */
@@ -748,7 +775,7 @@
clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%s%c%i%c" /* "ms"=password\1version\1getContacts\1 */
"%s%c%s%c%i%c" /* capabilities\1dc\1features\1 */
"%s%c%s%c" /* dialingcode\1locale\1 */
@@ -762,7 +789,7 @@
/* include "custom resource" information */
splashId = splash_current( session );
if ( splashId != NULL )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%ccr=%s", CP_REC_TERM, splashId );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%ccr=%s", CP_REC_TERM, splashId );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_LOGIN );
@@ -792,7 +819,7 @@
markuped_msg = g_strdup( msg );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%s%c%i%c%i", /* "ms"=jid\1msg\1type\1flags */
to, CP_FLD_TERM, markuped_msg, CP_FLD_TERM, msgtype, CP_FLD_TERM, CP_MSG_MARKUP | CP_MSG_EMOTICON
);
@@ -819,14 +846,14 @@
int datalen;
unsigned int i;
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%i", /* "ms="mxitid\1nr_attributes */
( username ? username : "" ), CP_FLD_TERM, nr_attrib
);
/* add attributes */
for ( i = 0; i < nr_attrib; i++ )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET );
@@ -852,7 +879,7 @@
parts = g_strsplit( attributes, "\01", 1 + ( nr_attrib * 3 ) );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%i", /* "ms"=password\1nr_attibutes */
( password ) ? password : "", CP_FLD_TERM, nr_attrib
);
@@ -864,7 +891,7 @@
g_strfreev( parts );
return;
}
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen,
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen,
"%c%s%c%s%c%s", /* \1name\1type\1value */
CP_FLD_TERM, parts[i], CP_FLD_TERM, parts[i + 1], CP_FLD_TERM, parts[i + 2] );
}
@@ -892,13 +919,13 @@
unsigned int i;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
CP_SUGGEST_FRIENDS, CP_FLD_TERM, "", CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
/* add attributes */
for ( i = 0; i < nr_attrib; i++ )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
@@ -921,13 +948,13 @@
unsigned int i;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
CP_SUGGEST_SEARCH, CP_FLD_TERM, text, CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
/* add attributes */
for ( i = 0; i < nr_attrib; i++ )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
@@ -947,14 +974,14 @@
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%i%c", /* "ms"=show\1status */
presence, CP_FLD_TERM
);
/* append status message (if one is set) */
if ( statusmsg )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%s", statusmsg );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%s", statusmsg );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_STATUS );
@@ -973,7 +1000,7 @@
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%i", /* "ms"=mood */
mood
);
@@ -999,7 +1026,7 @@
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%s%c%s%c%i%c%s%c%i", /* "ms"=group \1 username \1 alias \1 type \1 msg \1 isuserid */
groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias,
CP_FLD_TERM, MXIT_TYPE_MXIT, CP_FLD_TERM,
@@ -1024,7 +1051,7 @@
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s", /* "ms"=username */
username
);
@@ -1047,7 +1074,7 @@
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%s%c%s", /* "ms"=username\1group\1alias */
username, CP_FLD_TERM, "", CP_FLD_TERM, alias
);
@@ -1070,14 +1097,14 @@
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s", /* "ms"=username */
username
);
/* append reason (if one is set) */
if ( reason )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, reason );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, reason );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_DENY );
@@ -1098,7 +1125,7 @@
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%s%c%s", /* "ms"=groupname\1username\1alias */
groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias
);
@@ -1120,7 +1147,7 @@
int datalen;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s", /* "ms"=splashId */
splashid
);
@@ -1146,7 +1173,7 @@
purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_msgevent: to=%s id=%s event=%i\n", to, id, event );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%s%c%i", /* "ms"=contactAddress \1 id \1 event */
to, CP_FLD_TERM, id, CP_FLD_TERM, event
);
@@ -1171,14 +1198,14 @@
int i;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%i", /* "ms"=roomname\1nr_jids\1jid0\1..\1jidN */
groupname, CP_FLD_TERM, nr_usernames
);
/* add usernames */
for ( i = 0; i < nr_usernames; i++ )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE );
@@ -1200,14 +1227,14 @@
int i;
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ),
+ datalen = scnprintf( data, sizeof( data ),
"ms=%s%c%i", /* "ms"=roomid\1nr_jids\1jid0\1..\1jidN */
roomid, CP_FLD_TERM, nr_usernames
);
/* add usernames */
for ( i = 0; i < nr_usernames; i++ )
- datalen += g_snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
+ datalen += scnprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
/* queue packet for transmission */
mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE );
@@ -1233,7 +1260,7 @@
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=" );
+ datalen = scnprintf( data, sizeof( data ), "ms=" );
/* map chunk header over data buffer */
chunk = &data[datalen];
@@ -1265,7 +1292,7 @@
purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ), "ms=" );
+ datalen = scnprintf( data, sizeof( data ), "ms=" );
/* map chunk header over data buffer */
chunk = &data[datalen];
@@ -1299,7 +1326,7 @@
purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ), "ms=" );
+ datalen = scnprintf( data, sizeof( data ), "ms=" );
/* map chunk header over data buffer */
chunk = &data[datalen];
@@ -1331,7 +1358,7 @@
purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ), "ms=" );
+ datalen = scnprintf( data, sizeof( data ), "ms=" );
/* map chunk header over data buffer */
chunk = &data[datalen];
@@ -1364,7 +1391,7 @@
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=" );
+ datalen = scnprintf( data, sizeof( data ), "ms=" );
/* map chunk header over data buffer */
chunk = &data[datalen];
@@ -1399,7 +1426,7 @@
purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId );
/* convert the packet to a byte stream */
- datalen = g_snprintf( data, sizeof( data ), "ms=" );
+ datalen = scnprintf( data, sizeof( data ), "ms=" );
/* map chunk header over data buffer */
chunk = &data[datalen];