Merge from release-2.x.y branch. No manual merges.

Sat, 12 Apr 2014 22:30:26 -0700

author
Mark Doliner <mark@kingant.net>
date
Sat, 12 Apr 2014 22:30:26 -0700
changeset 36182
93a7252bf87c
parent 35842
82fdaf2769b5 (current diff)
parent 36181
a324d01ba1c5 (diff)
child 36183
c3cad56ac8b9

Merge from release-2.x.y branch. No manual merges.

ChangeLog file | annotate | diff | comparison | revisions
libpurple/protocols/mxit/markup.c file | annotate | diff | comparison | revisions
--- a/ChangeLog	Sun Apr 13 02:17:31 2014 +0200
+++ b/ChangeLog	Sat Apr 12 22:30:26 2014 -0700
@@ -69,15 +69,28 @@
 	* Doxygen has been replaced by gtk-doc for generating documentation.
 
 version 2.10.10 (?/?/?):
+	Windows-Specific Changes:
+	* Don't allow overwriting arbitrary files on the file system when the
+	  user installs a smiley theme via drag-and-drop. (Discovered by Yves
+	  Younan of Sourcefire VRT)
+	* Updates to dependencies:
+		* NSS 3.16 and NSPR 4.10.4
+
 	Finch:
 	* Fix build against Python 3. (Ed Catmur) (#15969)
 
 	Gadu-Gadu:
 	* Updated internal libgadu to version 1.12.0-rc2.
 
-	Windows-Specific Changes:
-	* Updates to dependencies:
-		* NSS 3.16 and NSPR 4.10.4
+	Groupwise:
+	* Fix potential remote crash parsing server message that indicates that
+	  a large amount of memory should be allocated. (Discovered by Yves Younan
+	  and Richard Johnson of Sourcefire VRT) (CVE-2014-NNNN)
+
+	MXit:
+	* Fix potential remote crash parsing a malformed emoticon response.
+	  (Discovered by Yves Younan and Richard Johnson of Sourcefire VRT)
+	  (CVE-2014-NNNN)
 
 version 2.10.9 (2/2/2014):
 	XMPP:
--- a/libpurple/protocols/mxit/markup.c	Sun Apr 13 02:17:31 2014 +0200
+++ b/libpurple/protocols/mxit/markup.c	Sat Apr 12 22:30:26 2014 -0700
@@ -165,16 +165,22 @@
  * Extract an ASN.1 formatted length field from the data.
  *
  *  @param data				The source data
+ *  @param data_len			Length of data
  *  @param size				The extracted length
  *  @return					The number of bytes extracted
  */
-static unsigned int asn_getlength( const gchar* data, int* size )
+static unsigned int asn_getlength( const gchar* data, gsize data_len, int* size )
 {
 	unsigned int	len		= 0;
 	unsigned char	bytes;
 	unsigned char	byte;
 	int				i;
 
+	if ( data_len < 1 ) {
+		/* missing first byte! */
+		return -1;
+	}
+
 	/* first byte specifies the number of bytes in the length */
 	bytes = ( data[0] & ~0x80 );
 	if ( bytes > sizeof( unsigned int ) ) {
@@ -183,6 +189,11 @@
 	}
 	data++;
 
+	if ( data_len - 1 < bytes ) {
+		/* missing length! */
+		return -1;
+	}
+
 	/* parse out the actual length */
 	for ( i = 0; i < bytes; i++ ) {
 		byte = data[i];
@@ -199,15 +210,21 @@
  * Extract an ASN.1 formatted UTF-8 string field from the data.
  *
  *  @param data				The source data
+ *  @param data_len			Length of data
  *  @param type				Expected type of string
  *  @param utf8				The extracted string.  Must be deallocated by caller.
  *  @return					The number of bytes extracted
  */
-static int asn_getUtf8( const gchar* data, gchar type, char** utf8 )
+static int asn_getUtf8( const gchar* data, gsize data_len, gchar type, char** utf8 )
 {
 	unsigned int len;
 	gchar *out_str;
 
+	if ( data_len < 2 ) {
+		/* missing type or length! */
+		return -1;
+	}
+
 	/* validate the field type [1 byte] */
 	if ( data[0] != type ) {
 		/* this is not a utf-8 string! */
@@ -216,6 +233,11 @@
 	}
 
 	len = (guint8)data[1]; /* length field [1 byte] */
+	if ( data_len - 2 < len ) {
+		/* not enough bytes left in data! */
+		return -1;
+	}
+
 	out_str = g_malloc(len + 1);
 	memcpy(out_str, &data[2], len); /* data field */
 	out_str[len] = '\0';
@@ -501,7 +523,7 @@
 #endif
 
 	/* validate that the returned data starts with the magic constant that indicates it is a custom emoticon */
-	if ( memcmp( MXIT_FRAME_MAGIC, &data[pos], strlen( MXIT_FRAME_MAGIC ) ) != 0 ) {
+	if ( len - pos < strlen( MXIT_FRAME_MAGIC ) || memcmp( MXIT_FRAME_MAGIC, &data[pos], strlen( MXIT_FRAME_MAGIC ) ) != 0 ) {
 		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad magic)\n" );
 		goto done;
 	}
@@ -515,7 +537,7 @@
 	pos++;
 
 	/* get the frame image data length */
-	res = asn_getlength( &data[pos], &em_size );
+	res = asn_getlength( &data[pos], len - pos, &em_size );
 	if ( res <= 0 ) {
 		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad frame length)\n" );
 		goto done;
@@ -526,7 +548,7 @@
 #endif
 
 	/* utf-8 (emoticon name) */
-	res = asn_getUtf8( &data[pos], 0x0C, &str );
+	res = asn_getUtf8( &data[pos], len - pos, 0x0C, &str );
 	if ( res <= 0 ) {
 		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad name string)\n" );
 		goto done;
@@ -539,7 +561,7 @@
 	str = NULL;
 
 	/* utf-8 (emoticon shortcut) */
-	res = asn_getUtf8( &data[pos], 0x81, &str );
+	res = asn_getUtf8( &data[pos], len - pos, 0x81, &str );
 	if ( res <= 0 ) {
 		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad shortcut string)\n" );
 		goto done;
@@ -551,7 +573,7 @@
 	em_id = str;
 
 	/* validate the image data type */
-	if ( data[pos] != '\x82' ) {
+	if ( len - pos < 1 || data[pos] != '\x82' ) {
 		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad data type)\n" );
 		g_free( em_id );
 		goto done;
@@ -559,7 +581,7 @@
 	pos++;
 
 	/* get the data length */
-	res = asn_getlength( &data[pos], &em_size );
+	res = asn_getlength( &data[pos], len - pos, &em_size );
 	if ( res <= 0 ) {
 		/* bad frame length */
 		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad data length)\n" );
@@ -571,6 +593,13 @@
 	purple_debug_info( MXIT_PLUGIN_ID, "read the length '%i'\n", em_size );
 #endif
 
+	if ( len - pos < em_size ) {
+		/* not enough bytes left in data! */
+		purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (data length too long)\n");
+		g_free( em_id );
+		goto done;
+	}
+
 	/* strip the mxit markup tags from the emoticon id (eg, .{XY} -> XY) */
 	if ( ( em_id[0] == '.' ) && ( em_id[1] == '{' ) ) {
 		char	emo[MXIT_MAX_EMO_ID + 1];
--- a/libpurple/protocols/novell/nmevent.c	Sun Apr 13 02:17:31 2014 +0200
+++ b/libpurple/protocols/novell/nmevent.c	Sat Apr 12 22:30:26 2014 -0700
@@ -149,7 +149,7 @@
 
 	/* Read the conference guid */
 	rc = nm_read_uint32(conn, &size);
-	if (size == MAX_UINT32)	return NMERR_PROTOCOL;
+	if (size > 1000)	return NMERR_PROTOCOL;
 
 	if (rc == NM_OK) {
 		guid = g_new0(char, size + 1);
@@ -164,7 +164,7 @@
 	/* Read the message text */
 	if (rc == NM_OK) {
 		rc = nm_read_uint32(conn, &size);
-		if (size == MAX_UINT32)	return NMERR_PROTOCOL;
+		if (size > 100000)	return NMERR_PROTOCOL;
 
 		if (rc == NM_OK) {
 			msg = g_new0(char, size + 1);
@@ -270,7 +270,7 @@
 
 	/* Read the conference guid */
 	rc = nm_read_uint32(conn, &size);
-	if (size == MAX_UINT32)	return NMERR_PROTOCOL;
+	if (size > 1000)	return NMERR_PROTOCOL;
 
 	if (rc == NM_OK) {
 		guid = g_new0(char, size + 1);
@@ -280,7 +280,7 @@
 	/* Read the the message */
 	if (rc == NM_OK) {
 		rc = nm_read_uint32(conn, &size);
-		if (size == MAX_UINT32)	return NMERR_PROTOCOL;
+		if (size > 100000)	return NMERR_PROTOCOL;
 
 		if (rc == NM_OK) {
 			msg = g_new0(char, size + 1);
@@ -349,7 +349,7 @@
 
 	/* Read the conference guid */
 	rc = nm_read_uint32(conn, &size);
-	if (size == MAX_UINT32)	return NMERR_PROTOCOL;
+	if (size > 1000)	return NMERR_PROTOCOL;
 
 	if (rc == NM_OK) {
 		guid = g_new0(char, size + 1);
@@ -401,7 +401,7 @@
 
 	/* Read the conference guid */
 	rc = nm_read_uint32(conn, &size);
-	if (size == MAX_UINT32)	return NMERR_PROTOCOL;
+	if (size > 1000)	return NMERR_PROTOCOL;
 
 	if (rc == NM_OK) {
 		guid = g_new0(char, size + 1);
@@ -440,7 +440,7 @@
 
 	/* Read the conference guid */
 	rc = nm_read_uint32(conn, &size);
-	if (size == MAX_UINT32)	return NMERR_PROTOCOL;
+	if (size > 1000)	return NMERR_PROTOCOL;
 
 	if (rc == NM_OK) {
 		guid = g_new0(char, size + 1);
@@ -490,7 +490,7 @@
 
 	/* Read the conference guid */
 	rc = nm_read_uint32(conn, &size);
-	if (size == MAX_UINT32)	return NMERR_PROTOCOL;
+	if (size > 1000)	return NMERR_PROTOCOL;
 
 	if (rc == NM_OK) {
 		guid = g_new0(char, size + 1);
@@ -530,7 +530,7 @@
 
 	/* Read the conference guid */
 	rc = nm_read_uint32(conn, &size);
-	if (size == MAX_UINT32)	return NMERR_PROTOCOL;
+	if (size > 1000)	return NMERR_PROTOCOL;
 
 	if (rc == NM_OK) {
 		guid = g_new0(char, size + 1);
@@ -589,7 +589,7 @@
 
 	/* Read the conference guid */
 	rc = nm_read_uint32(conn, &size);
-	if (size == MAX_UINT32)	return NMERR_PROTOCOL;
+	if (size > 1000)	return NMERR_PROTOCOL;
 
 	if (rc == NM_OK) {
 		guid = g_new0(char, size + 1);
@@ -632,7 +632,7 @@
 
 		/* Read the status text */
 		rc = nm_read_uint32(conn, &size);
-		if (size == MAX_UINT32)	return NMERR_PROTOCOL;
+		if (size > 10000)	return NMERR_PROTOCOL;
 
 		if (rc == NM_OK) {
 			text = g_new0(char, size + 1);
@@ -670,7 +670,7 @@
 
 	/* Read the conference guid */
 	rc = nm_read_uint32(conn, &size);
-	if (size == MAX_UINT32)	return NMERR_PROTOCOL;
+	if (size > 1000)	return NMERR_PROTOCOL;
 
 	if (rc == NM_OK) {
 		guid = g_new0(char, size + 1);
@@ -833,7 +833,10 @@
 	/* Read the event source */
 	rc = nm_read_uint32(conn, &size);
 	if (rc == NM_OK) {
-		if (size > 0) {
+		if (size > 1000000) {
+			/* Size is larger than our 1MB sanity check. Ignore it. */
+			rc = NMERR_PROTOCOL;
+		} else {
 			source = g_new0(char, size);
 
 			rc = nm_read_all(conn, source, size);
--- a/pidgin/win32/untar.c	Sun Apr 13 02:17:31 2014 +0200
+++ b/pidgin/win32/untar.c	Sat Apr 12 22:30:26 2014 -0700
@@ -122,8 +122,6 @@
 static FILE	  *infp    = NULL;      /* input byte stream */
 static FILE	  *outfp   = NULL;      /* output stream, for file currently being extracted */
 static Ulong_t	  outsize  = 0;         /* number of bytes remainin in file currently being extracted */
-static char	  **only   = NULL;      /* array of filenames to extract/list */
-static int	  nonlys   = 0;	        /* number of filenames in "only" array; 0=extract all */
 static int	  didabs   = 0;	        /* were any filenames affected by the absence of -p? */
 
 static untar_opt untarops = 0;          /* Untar options */
@@ -323,7 +321,7 @@
 
 /* list files in an archive, and optionally extract them as well */
 static int untar_block(Uchar_t *blk) {
-	static char	nbuf[256];/* storage space for prefix+name, combined */
+	static char	nbuf[4096];/* storage space for prefix+name, combined */
 	static char	*name,*n2;/* prefix and name, combined */
 	static int	first = 1;/* Boolean: first block of archive? */
 	long		sum;	  /* checksum for this block */
@@ -392,24 +390,35 @@
 
 		/* combine prefix and filename */
 		memset(nbuf, 0, sizeof nbuf);
-		name = nbuf;
 		if ((tblk)->prefix[0])
 		{
-			strncpy(name, (tblk)->prefix, sizeof (tblk)->prefix);
-			strcat(name, "/");
-			strncat(name + strlen(name), (tblk)->filename,
-				sizeof (tblk)->filename);
+			snprintf(nbuf, sizeof(nbuf), "%s/%s",
+				(tblk)->prefix, (tblk)->filename);
 		}
 		else
 		{
-			strncpy(name, (tblk)->filename,
-				sizeof (tblk)->filename);
+			g_strlcpy(nbuf, (tblk)->filename,
+				sizeof (nbuf));
+		}
+
+		/* Possibly strip the drive from the path */
+		if (!ABSPATH) {
+			/* If the path contains a colon, assume everything before the
+			 * colon is intended to be a drive name and ignore it. This
+			 * should be just a single drive letter, but it should be safe
+			 * to drop it even if it's longer. */
+			const char *lastcolon = strrchr(nbuf, ':');
+			if (lastcolon) {
+				memmove(nbuf, lastcolon, strlen(lastcolon) + 1);
+				didabs = 1; /* Path was changed from absolute to relative */
+			}
 		}
 
 		/* Convert any backslashes to forward slashes, and guard
 		 * against doubled-up slashes. (Some DOS versions of "tar"
 		 * get this wrong.)  Also strip off leading slashes.
 		 */
+		name = nbuf;
 		if (!ABSPATH && (*name == '/' || *name == '\\'))
 			didabs = 1;
 		for (n2 = nbuf; *name; name++)
@@ -474,26 +483,6 @@
 		}
 #endif
 
-		/* If we have an "only" list, and this file isn't in it,
-		 * then skip it.
-		 */
-		if (nonlys > 0)
-		{
-			for (i = 0;
-			     i < nonlys
-				&& strcmp(only[i], nbuf)
-				&& (strncmp(only[i], nbuf, strlen(only[i]))
-					|| nbuf[strlen(only[i])] != '/');
-				i++)
-			{
-			}
-			if (i >= nonlys)
-			{
-				outfp = NULL;
-				return 1;
-			}
-		}
-
 		/* list the file */
 		if (VERBOSE)
 			untar_verbose("%c %s",
@@ -520,18 +509,19 @@
 		 */
 		if (tblk->type == '5')
 		{
+			char *tmp;
 			if (LISTING)
-				n2 = " directory";
+				tmp = " directory";
 #ifdef _POSIX_SOURCE
 			else if (mkdir(nbuf, mode) == 0)
 #else
 			else if (g_mkdir(nbuf, 0755) == 0)
 #endif
-				n2 = " created";
+				tmp = " created";
 			else
-				n2 = " ignored";
+				tmp = " ignored";
 			if (VERBOSE)
-				untar_verbose("%s\n", n2);
+				untar_verbose("%s\n", tmp);
 			return 1;
 		}
 

mercurial