[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#655178: pu: package pidgin/2.7.3-1+squeeze1



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: pu

The security team asked me to prepare an update for squeeze that
includes fixes for the outstanding minor security issues (all remote
crashers with no remote code execution). That diff is attached.

-- System Information:
Debian Release: wheezy/sid
  APT prefers testing
  APT policy: (600, 'testing'), (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 3.1.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
diff --git a/debian/changelog b/debian/changelog
index 5406328..716ca65 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,16 @@
+pidgin (2.7.3-1+squeeze2) squeeze; urgency=medium
+
+  * CVE-2011-3594.patch:
+    - fix a SILC remote crash bug
+  * CVE-2011-4601.patch:
+    - fix an AIM/ICQ remote crash bug
+  * CVE-2011-4602.patch:
+    - fix an XMPP remote crash bug
+  * CVE-2011-4603.patch:
+    - fix a SILC remote crash bug
+
+ -- Ari Pollak <ari@debian.org>  Sat, 07 Jan 2012 21:47:12 -0500
+
 pidgin (2.7.3-1+squeeze1) squeeze; urgency=medium
 
   * baseXX_decode_error_handling_2.patch:
diff --git a/debian/patches/CVE-2011-3594.patch b/debian/patches/CVE-2011-3594.patch
new file mode 100644
index 0000000..98210d0
--- /dev/null
+++ b/debian/patches/CVE-2011-3594.patch
@@ -0,0 +1,28 @@
+Description: fix SILC remote crash
+#
+#
+# patch "libpurple/protocols/silc/ops.c"
+#  from [30ab18780af11a53b6564a44c4e8ebfc1a296d78]
+#    to [80bd9a7d3faf9e5ef28438647159fe19847e9839]
+#
+============================================================
+--- pidgin/libpurple/protocols/silc/ops.c	30ab18780af11a53b6564a44c4e8ebfc1a296d78
++++ pidgin/libpurple/protocols/silc/ops.c	80bd9a7d3faf9e5ef28438647159fe19847e9839
+@@ -408,9 +408,16 @@ silc_private_message(SilcClient client, 
+ 	}
+ 
+ 	if (flags & SILC_MESSAGE_FLAG_UTF8) {
+-		tmp = g_markup_escape_text((const char *)message, -1);
++		const char *msg = (const char *)message;
++		char *salvaged = NULL;
++		if (!g_utf8_validate((const char *)message, -1, NULL)) {
++			salvaged = purple_utf8_salvage((const char *)message);
++			msg = salvaged;
++		}
++		tmp = g_markup_escape_text(msg, -1);
+ 		/* Send to Purple */
+ 		serv_got_im(gc, sender->nickname, tmp, 0, time(NULL));
++		g_free(salvaged);
+ 		g_free(tmp);
+ 	}
+ }
diff --git a/debian/patches/CVE-2011-4601.patch b/debian/patches/CVE-2011-4601.patch
new file mode 100644
index 0000000..2e1c16f
--- /dev/null
+++ b/debian/patches/CVE-2011-4601.patch
@@ -0,0 +1,168 @@
+Description: fix AIM and ICQ remote crash
+#
+#
+# patch "libpurple/protocols/oscar/family_feedbag.c"
+#  from [8f80e2c5acd2b21acc88d54ba8e5ab43dbdaa3e2]
+#    to [ff8702078ba3a5c73ff1c86a206f09f7749c1314]
+#
+============================================================
+--- pidgin/libpurple/protocols/oscar/family_feedbag.c	8f80e2c5acd2b21acc88d54ba8e5ab43dbdaa3e2
++++ pidgin/libpurple/protocols/oscar/family_feedbag.c	ff8702078ba3a5c73ff1c86a206f09f7749c1314
+@@ -1650,18 +1650,35 @@ static int receiveauthgrant(OscarData *o
+ 	int ret = 0;
+ 	aim_rxcallback_t userfunc;
+ 	guint16 tmp;
+-	char *bn, *msg;
++	char *bn, *msg, *tmpstr;
+ 
+ 	/* Read buddy name */
+-	if ((tmp = byte_stream_get8(bs)))
+-		bn = byte_stream_getstr(bs, tmp);
+-	else
+-		bn = NULL;
++	tmp = byte_stream_get8(bs);
++	if (!tmp) {
++		purple_debug_warning("oscar", "Dropping auth grant SNAC "
++				"because username was empty\n");
++		return 0;
++	}
++	bn = byte_stream_getstr(bs, tmp);
++	if (!g_utf8_validate(bn, -1, NULL)) {
++		purple_debug_warning("oscar", "Dropping auth grant SNAC "
++				"because the username was not valid UTF-8\n");
++		g_free(bn);
++	}
+ 
+-	/* Read message (null terminated) */
+-	if ((tmp = byte_stream_get16(bs)))
++	/* Read message */
++	tmp = byte_stream_get16(bs);
++	if (tmp) {
+ 		msg = byte_stream_getstr(bs, tmp);
+-	else
++		if (!g_utf8_validate(msg, -1, NULL)) {
++			/* Ugh, msg isn't UTF8.  Let's salvage. */
++			purple_debug_warning("oscar", "Got non-UTF8 message in auth "
++					"grant from %s\n", bn);
++			tmpstr = purple_utf8_salvage(msg);
++			g_free(msg);
++			msg = tmpstr;
++		}
++	} else
+ 		msg = NULL;
+ 
+ 	/* Unknown */
+@@ -1724,18 +1741,35 @@ static int receiveauthrequest(OscarData 
+ 	int ret = 0;
+ 	aim_rxcallback_t userfunc;
+ 	guint16 tmp;
+-	char *bn, *msg;
++	char *bn, *msg, *tmpstr;
+ 
+ 	/* Read buddy name */
+-	if ((tmp = byte_stream_get8(bs)))
+-		bn = byte_stream_getstr(bs, tmp);
+-	else
+-		bn = NULL;
++	tmp = byte_stream_get8(bs);
++	if (!tmp) {
++		purple_debug_warning("oscar", "Dropping auth request SNAC "
++				"because username was empty\n");
++		return 0;
++	}
++	bn = byte_stream_getstr(bs, tmp);
++	if (!g_utf8_validate(bn, -1, NULL)) {
++		purple_debug_warning("oscar", "Dropping auth request SNAC "
++				"because the username was not valid UTF-8\n");
++		g_free(bn);
++	}
+ 
+-	/* Read message (null terminated) */
+-	if ((tmp = byte_stream_get16(bs)))
++	/* Read message */
++	tmp = byte_stream_get16(bs);
++	if (tmp) {
+ 		msg = byte_stream_getstr(bs, tmp);
+-	else
++		if (!g_utf8_validate(msg, -1, NULL)) {
++			/* Ugh, msg isn't UTF8.  Let's salvage. */
++			purple_debug_warning("oscar", "Got non-UTF8 message in auth "
++					"request from %s\n", bn);
++			tmpstr = purple_utf8_salvage(msg);
++			g_free(msg);
++			msg = tmpstr;
++		}
++	} else
+ 		msg = NULL;
+ 
+ 	/* Unknown */
+@@ -1808,21 +1842,38 @@ static int receiveauthreply(OscarData *o
+ 	aim_rxcallback_t userfunc;
+ 	guint16 tmp;
+ 	guint8 reply;
+-	char *bn, *msg;
++	char *bn, *msg, *tmpstr;
+ 
+ 	/* Read buddy name */
+-	if ((tmp = byte_stream_get8(bs)))
+-		bn = byte_stream_getstr(bs, tmp);
+-	else
+-		bn = NULL;
++	tmp = byte_stream_get8(bs);
++	if (!tmp) {
++		purple_debug_warning("oscar", "Dropping auth reply SNAC "
++				"because username was empty\n");
++		return 0;
++	}
++	bn = byte_stream_getstr(bs, tmp);
++	if (!g_utf8_validate(bn, -1, NULL)) {
++		purple_debug_warning("oscar", "Dropping auth reply SNAC "
++				"because the username was not valid UTF-8\n");
++		g_free(bn);
++	}
+ 
+ 	/* Read reply */
+ 	reply = byte_stream_get8(bs);
+ 
+-	/* Read message (null terminated) */
+-	if ((tmp = byte_stream_get16(bs)))
++	/* Read message */
++	tmp = byte_stream_get16(bs);
++	if (tmp) {
+ 		msg = byte_stream_getstr(bs, tmp);
+-	else
++		if (!g_utf8_validate(msg, -1, NULL)) {
++			/* Ugh, msg isn't UTF8.  Let's salvage. */
++			purple_debug_warning("oscar", "Got non-UTF8 message in auth "
++					"reply from %s\n", bn);
++			tmpstr = purple_utf8_salvage(msg);
++			g_free(msg);
++			msg = tmpstr;
++		}
++	} else
+ 		msg = NULL;
+ 
+ 	/* Unknown */
+@@ -1848,10 +1899,18 @@ static int receiveadded(OscarData *od, F
+ 	char *bn;
+ 
+ 	/* Read buddy name */
+-	if ((tmp = byte_stream_get8(bs)))
+-		bn = byte_stream_getstr(bs, tmp);
+-	else
+-		bn = NULL;
++	tmp = byte_stream_get8(bs);
++	if (!tmp) {
++		purple_debug_warning("oscar", "Dropping 'you were added' SNAC "
++				"because username was empty\n");
++		return 0;
++	}
++	bn = byte_stream_getstr(bs, tmp);
++	if (!g_utf8_validate(bn, -1, NULL)) {
++		purple_debug_warning("oscar", "Dropping 'you were added' SNAC "
++				"because the username was not valid UTF-8\n");
++		g_free(bn);
++	}
+ 
+ 	if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+ 		ret = userfunc(od, conn, frame, bn);
diff --git a/debian/patches/CVE-2011-4602.patch b/debian/patches/CVE-2011-4602.patch
new file mode 100644
index 0000000..e3c5688
--- /dev/null
+++ b/debian/patches/CVE-2011-4602.patch
@@ -0,0 +1,446 @@
+Description: fix XMPP remote crash
+#
+#
+# patch "libpurple/protocols/jabber/jingle/jingle.c" from
+# [185980c698f1c26bad6f0f8a23e866c0645ea1d9] to
+# [2933cb6d81371155c69a5a4f97b6b3bf09aa5aa5]
+# 
+# patch "libpurple/protocols/jabber/jingle/rtp.c" from
+# [2656346b8bf03a7995ef995e7c2e154facdf905e] to
+# [dcacf06a52d80015f7bc1676b1ccbdb182276784]
+# 
+# patch "libpurple/protocols/jabber/jingle/session.c" from
+# [00e7dd7888866a805129a8f17a545159c7e6e378] to
+# [6f394c4ccad3d4ef658116e13e9db59d4b4a46fb]
+#
+============================================================ Index:
+pidgin/libpurple/protocols/jabber/jingle/jingle.c
+=================================================================== ---
+pidgin.orig/libpurple/protocols/jabber/jingle/jingle.c +++
+pidgin/libpurple/protocols/jabber/jingle/jingle.c @@ -119,7 +119,7 @@
+jingle_handle_content_modify(JingleSessi if (local_content != NULL) { const
+gchar *senders = xmlnode_get_attrib(content, "senders"); gchar *local_senders =
+jingle_content_get_senders(local_content);
+-			if (strcmp(senders,
+			local_senders)) +			if
+(!purple_strequal(senders, local_senders)) jingle_content_modify(local_content,
+senders); g_free(local_senders); } else { Index:
+pidgin/libpurple/protocols/jabber/jingle/rtp.c
+=================================================================== ---
+pidgin.orig/libpurple/protocols/jabber/jingle/rtp.c +++
+pidgin/libpurple/protocols/jabber/jingle/rtp.c @@ -589,6 +589,16 @@
+jingle_rtp_init_media(JingleContent *con senders =
+jingle_content_get_senders(content); transport =
+jingle_content_get_transport(content);
+ 
++	if (media_type == NULL) { +		g_free(name); +
+g_free(remote_jid); +		g_free(senders); +
+g_free(params); +		g_object_unref(transport); +
+g_object_unref(session); +		return FALSE; +	} + if
+(JINGLE_IS_RAWUDP(transport)) transmitter = "rawudp"; else if
+(JINGLE_IS_ICEUDP(transport)) @@ -597,24 +607,34 @@
+jingle_rtp_init_media(JingleContent *con transmitter = "notransmitter";
+g_object_unref(transport);
+ 
+-	is_audio = !strcmp(media_type, "audio"); +	is_audio =
+	g_str_equal(media_type, "audio");
+ 
+-	if (!strcmp(senders, "both"))
+-		type = is_audio == TRUE ? PURPLE_MEDIA_AUDIO +	if
+		(purple_strequal(senders, "both")) +		type =
+is_audio ? PURPLE_MEDIA_AUDIO : PURPLE_MEDIA_VIDEO;
+-	else if ((strcmp(senders, "initiator") == 0) == +	else if
+	(purple_strequal(senders, "initiator") ==
+jingle_session_is_initiator(session))
+-		type = is_audio == TRUE ?
+		PURPLE_MEDIA_SEND_AUDIO +		type = is_audio ?
+PURPLE_MEDIA_SEND_AUDIO : PURPLE_MEDIA_SEND_VIDEO; else
+-		type = is_audio == TRUE ?
+		PURPLE_MEDIA_RECV_AUDIO +		type = is_audio ?
+PURPLE_MEDIA_RECV_AUDIO : PURPLE_MEDIA_RECV_VIDEO;
+ 
+	params = jingle_get_params(jingle_session_get_js(session),
+&num_params);
+ 
+	creator = jingle_content_get_creator(content);
+-	if (!strcmp(creator, "initiator")) +	if (creator == NULL)
+	{ +		g_free(name); +		g_free(media_type); +
+g_free(remote_jid); +		g_free(senders); +
+g_free(params); +		g_object_unref(session); +		return
+FALSE; +	} + +	if (g_str_equal(creator, "initiator")) is_creator =
+jingle_session_is_initiator(session); else is_creator =
+!jingle_session_is_initiator(session); @@ -623,6 +643,8 @@
+jingle_rtp_init_media(JingleContent *con if(!purple_media_add_stream(media,
+name, remote_jid, type, is_creator, transmitter, num_params, params)) {
+purple_media_end(media, NULL, NULL); +		/* TODO: How much clean-up is
+necessary here? (does calling +		         purple_media_end lead to
+cleaning up Jingle structs?) */ return FALSE; }
+ 
+@@ -644,9 +666,22 @@ jingle_rtp_parse_codecs(xmlnode *descrip const char
+*encoding_name,*id, *clock_rate; PurpleMediaCodec *codec; const gchar *media =
+xmlnode_get_attrib(description, "media");
+-	PurpleMediaSessionType type =
+-			!strcmp(media, "video") ? PURPLE_MEDIA_VIDEO :
+-			!strcmp(media, "audio") ? PURPLE_MEDIA_AUDIO :
+			0; +	PurpleMediaSessionType type; + +	if
+(media == NULL) { +		purple_debug_warning("jingle-rtp", "missing
+media type\n"); +		return NULL; +	} + +	if (g_str_equal(media,
+"video")) { +		type = PURPLE_MEDIA_VIDEO; +	} else if
+(g_str_equal(media, "audio")) { +		type =
+PURPLE_MEDIA_AUDIO; +	} else { +
+purple_debug_warning("jingle-rtp", "unknown media type:
+%s\n", +				media); +		return
+NULL; +	}
+ 
+	for (codec_element = xmlnode_get_child(description, "payload-type") ;
+codec_element ; @@ -767,19 +802,19 @@ jingle_rtp_handle_action_internal(Jingle
+switch (action) { case JINGLE_SESSION_ACCEPT: case JINGLE_SESSION_INITIATE: {
+-			JingleSession *session =
+			jingle_content_get_session(content);
+-			JingleTransport *transport = jingle_transport_parse(
+-					xmlnode_get_child(xmlcontent,
+					"transport"));
+-			xmlnode *description = xmlnode_get_child(xmlcontent,
+			"description");
+-			GList *candidates =
+			jingle_rtp_transport_to_candidates(transport);
+-			GList *codecs = jingle_rtp_parse_codecs(description);
+-			gchar *name = jingle_content_get_name(content);
+-			gchar *remote_jid =
+-					jingle_session_get_remote_jid(session);
+					+			JingleSession
+*session; +			JingleTransport
+*transport; +			xmlnode *description; +			GList
+*candidates; +			GList *codecs; +			gchar
+*name; +			gchar *remote_jid; PurpleMedia *media;
+ 
++			session = jingle_content_get_session(content); + if
+(action == JINGLE_SESSION_INITIATE &&
+-					jingle_rtp_init_media(content) ==
+					FALSE)
+{ +					!jingle_rtp_init_media(content)) {
+				/* XXX: send error */
+				jabber_iq_send(jingle_session_terminate_packet(
+session, "general-error")); @@ -787,6 +822,14 @@
+jingle_rtp_handle_action_internal(Jingle break; }
+ 
++			transport =
+jingle_transport_parse( +
+xmlnode_get_child(xmlcontent, "transport")); +			description =
+xmlnode_get_child(xmlcontent, "description"); +			candidates =
+jingle_rtp_transport_to_candidates(transport); +			codecs
+= jingle_rtp_parse_codecs(description); +			name =
+jingle_content_get_name(content); +			remote_jid =
+jingle_session_get_remote_jid(session); + media =
+jingle_rtp_get_media(session); purple_media_set_remote_codecs(media, name,
+remote_jid, codecs); Index: pidgin/libpurple/protocols/jabber/jingle/session.c
+=================================================================== ---
+pidgin.orig/libpurple/protocols/jabber/jingle/session.c +++
+pidgin/libpurple/protocols/jabber/jingle/session.c @@ -284,7 +284,7 @@
+jingle_session_create(JabberStream *js, if (!js->sessions) {
+purple_debug_info("jingle", "Creating hash table for sessions\n");
+-		js->sessions = g_hash_table_new(g_str_hash,
+		g_str_equal); +		js->sessions =
+g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); }
+purple_debug_info("jingle", "inserting session with key: %s into table\n",
+sid); @@ -407,27 +407,25 @@ jingle_add_jingle_packet(JingleSession *
+xmlnode_new("jingle"); gchar *local_jid =
+jingle_session_get_local_jid(session); gchar *remote_jid =
+jingle_session_get_remote_jid(session); +	gchar *sid =
+jingle_session_get_sid(session);
+ 
+	xmlnode_set_namespace(jingle, JINGLE); xmlnode_set_attrib(jingle,
+"action", jingle_get_action_name(action));
+ 
+	if (jingle_session_is_initiator(session)) {
+-		xmlnode_set_attrib(jingle, "initiator",
+-				jingle_session_get_local_jid(session));
+-		xmlnode_set_attrib(jingle, "responder",
+-				jingle_session_get_remote_jid(session));
+				+		xmlnode_set_attrib(jingle,
+"initiator", local_jid); +		xmlnode_set_attrib(jingle, "responder",
+remote_jid); } else {
+-		xmlnode_set_attrib(jingle, "initiator",
+-				jingle_session_get_remote_jid(session));
+-		xmlnode_set_attrib(jingle, "responder",
+-				jingle_session_get_local_jid(session));
+				+		xmlnode_set_attrib(jingle,
+"initiator", remote_jid); +		xmlnode_set_attrib(jingle, "responder",
+local_jid); }
+ 
++	xmlnode_set_attrib(jingle, "sid", sid); + g_free(local_jid);
+g_free(remote_jid); +	g_free(sid);
+ 
+-	xmlnode_set_attrib(jingle, "sid", jingle_session_get_sid(session));
+-	
+	return jingle; }
+ 
+@@ -504,11 +502,16 @@ void jingle_session_handle_action(Jingle JingleContent *
+jingle_session_find_content(JingleSession *session, const gchar *name, const
+gchar *creator) {
+-	GList *iter = session->priv->contents; +	GList *iter; + +
+	if (name == NULL) +		return NULL; + +	iter =
+session->priv->contents; for (; iter; iter = g_list_next(iter)) {
+JingleContent *content = iter->data; gchar *cname =
+jingle_content_get_name(content);
+-		gboolean result = !strcmp(name, cname); +
+		gboolean result = g_str_equal(name, cname); g_free(cname);
+ 
+		if (creator != NULL) { @@ -526,11 +529,16 @@
+jingle_session_find_content(JingleSessio JingleContent *
+jingle_session_find_pending_content(JingleSession *session, const gchar *name,
+const gchar *creator) {
+-	GList *iter = session->priv->pending_contents; +	GList
+	*iter; + +	if (name == NULL) +		return NULL; +
++	iter = session->priv->pending_contents;
+ 	for (; iter; iter = g_list_next(iter)) {
+ 		JingleContent *content = iter->data;
+ 		gchar *cname = jingle_content_get_name(content);
+-		gboolean result = !strcmp(name, cname);
++		gboolean result = g_str_equal(name, cname);
+ 		g_free(cname);
+ 
+ 		if (creator != NULL) {
+Index: pidgin/libpurple/protocols/jabber/jingle/jingle.c
+===================================================================
+--- pidgin.orig/libpurple/protocols/jabber/jingle/jingle.c
++++ pidgin/libpurple/protocols/jabber/jingle/jingle.c
+@@ -119,7 +119,7 @@ jingle_handle_content_modify(JingleSessi
+ 		if (local_content != NULL) {
+ 			const gchar *senders = xmlnode_get_attrib(content, "senders");
+ 			gchar *local_senders = jingle_content_get_senders(local_content);
+-			if (strcmp(senders, local_senders))
++			if (!purple_strequal(senders, local_senders))
+ 				jingle_content_modify(local_content, senders);
+ 			g_free(local_senders);
+ 		} else {
+Index: pidgin/libpurple/protocols/jabber/jingle/rtp.c
+===================================================================
+--- pidgin.orig/libpurple/protocols/jabber/jingle/rtp.c
++++ pidgin/libpurple/protocols/jabber/jingle/rtp.c
+@@ -589,6 +589,16 @@ jingle_rtp_init_media(JingleContent *con
+ 	senders = jingle_content_get_senders(content);
+ 	transport = jingle_content_get_transport(content);
+ 
++	if (media_type == NULL) {
++		g_free(name);
++		g_free(remote_jid);
++		g_free(senders);
++		g_free(params);
++		g_object_unref(transport);
++		g_object_unref(session);
++		return FALSE;
++	}
++
+ 	if (JINGLE_IS_RAWUDP(transport))
+ 		transmitter = "rawudp";
+ 	else if (JINGLE_IS_ICEUDP(transport))
+@@ -597,24 +607,34 @@ jingle_rtp_init_media(JingleContent *con
+ 		transmitter = "notransmitter";
+ 	g_object_unref(transport);
+ 
+-	is_audio = !strcmp(media_type, "audio");
++	is_audio = g_str_equal(media_type, "audio");
+ 
+-	if (!strcmp(senders, "both"))
+-		type = is_audio == TRUE ? PURPLE_MEDIA_AUDIO
++	if (purple_strequal(senders, "both"))
++		type = is_audio ? PURPLE_MEDIA_AUDIO
+ 				: PURPLE_MEDIA_VIDEO;
+-	else if ((strcmp(senders, "initiator") == 0) ==
++	else if (purple_strequal(senders, "initiator") ==
+ 			jingle_session_is_initiator(session))
+-		type = is_audio == TRUE ? PURPLE_MEDIA_SEND_AUDIO
++		type = is_audio ? PURPLE_MEDIA_SEND_AUDIO
+ 				: PURPLE_MEDIA_SEND_VIDEO;
+ 	else
+-		type = is_audio == TRUE ? PURPLE_MEDIA_RECV_AUDIO
++		type = is_audio ? PURPLE_MEDIA_RECV_AUDIO
+ 				: PURPLE_MEDIA_RECV_VIDEO;
+ 
+ 	params = 
+ 		jingle_get_params(jingle_session_get_js(session), &num_params);
+ 
+ 	creator = jingle_content_get_creator(content);
+-	if (!strcmp(creator, "initiator"))
++	if (creator == NULL) {
++		g_free(name);
++		g_free(media_type);
++		g_free(remote_jid);
++		g_free(senders);
++		g_free(params);
++		g_object_unref(session);
++		return FALSE;
++	}
++
++	if (g_str_equal(creator, "initiator"))
+ 		is_creator = jingle_session_is_initiator(session);
+ 	else
+ 		is_creator = !jingle_session_is_initiator(session);
+@@ -623,6 +643,8 @@ jingle_rtp_init_media(JingleContent *con
+ 	if(!purple_media_add_stream(media, name, remote_jid,
+ 			type, is_creator, transmitter, num_params, params)) {
+ 		purple_media_end(media, NULL, NULL);
++		/* TODO: How much clean-up is necessary here? (does calling
++		         purple_media_end lead to cleaning up Jingle structs?) */
+ 		return FALSE;
+ 	}
+ 
+@@ -644,9 +666,22 @@ jingle_rtp_parse_codecs(xmlnode *descrip
+ 	const char *encoding_name,*id, *clock_rate;
+ 	PurpleMediaCodec *codec;
+ 	const gchar *media = xmlnode_get_attrib(description, "media");
+-	PurpleMediaSessionType type =
+-			!strcmp(media, "video") ? PURPLE_MEDIA_VIDEO :
+-			!strcmp(media, "audio") ? PURPLE_MEDIA_AUDIO : 0;
++	PurpleMediaSessionType type;
++
++	if (media == NULL) {
++		purple_debug_warning("jingle-rtp", "missing media type\n");
++		return NULL;
++	}
++
++	if (g_str_equal(media, "video")) {
++		type = PURPLE_MEDIA_VIDEO;
++	} else if (g_str_equal(media, "audio")) {
++		type = PURPLE_MEDIA_AUDIO;
++	} else {
++		purple_debug_warning("jingle-rtp", "unknown media type: %s\n",
++				media);
++		return NULL;
++	}
+ 
+ 	for (codec_element = xmlnode_get_child(description, "payload-type") ;
+ 		 codec_element ;
+@@ -767,19 +802,19 @@ jingle_rtp_handle_action_internal(Jingle
+ 	switch (action) {
+ 		case JINGLE_SESSION_ACCEPT:
+ 		case JINGLE_SESSION_INITIATE: {
+-			JingleSession *session = jingle_content_get_session(content);
+-			JingleTransport *transport = jingle_transport_parse(
+-					xmlnode_get_child(xmlcontent, "transport"));
+-			xmlnode *description = xmlnode_get_child(xmlcontent, "description");
+-			GList *candidates = jingle_rtp_transport_to_candidates(transport);
+-			GList *codecs = jingle_rtp_parse_codecs(description);
+-			gchar *name = jingle_content_get_name(content);
+-			gchar *remote_jid =
+-					jingle_session_get_remote_jid(session);
++			JingleSession *session;
++			JingleTransport *transport;
++			xmlnode *description;
++			GList *candidates;
++			GList *codecs;
++			gchar *name;
++			gchar *remote_jid;
+ 			PurpleMedia *media;
+ 
++			session = jingle_content_get_session(content);
++
+ 			if (action == JINGLE_SESSION_INITIATE &&
+-					jingle_rtp_init_media(content) == FALSE) {
++					!jingle_rtp_init_media(content)) {
+ 				/* XXX: send error */
+ 				jabber_iq_send(jingle_session_terminate_packet(
+ 						session, "general-error"));
+@@ -787,6 +822,14 @@ jingle_rtp_handle_action_internal(Jingle
+ 				break;
+ 			}
+ 
++			transport = jingle_transport_parse(
++					xmlnode_get_child(xmlcontent, "transport"));
++			description = xmlnode_get_child(xmlcontent, "description");
++			candidates = jingle_rtp_transport_to_candidates(transport);
++			codecs = jingle_rtp_parse_codecs(description);
++			name = jingle_content_get_name(content);
++			remote_jid = jingle_session_get_remote_jid(session);
++
+ 			media = jingle_rtp_get_media(session);
+ 			purple_media_set_remote_codecs(media,
+ 					name, remote_jid, codecs);
+Index: pidgin/libpurple/protocols/jabber/jingle/session.c
+===================================================================
+--- pidgin.orig/libpurple/protocols/jabber/jingle/session.c
++++ pidgin/libpurple/protocols/jabber/jingle/session.c
+@@ -284,7 +284,7 @@ jingle_session_create(JabberStream *js,
+ 	if (!js->sessions) {
+ 		purple_debug_info("jingle",
+ 				"Creating hash table for sessions\n");
+-		js->sessions = g_hash_table_new(g_str_hash, g_str_equal);
++		js->sessions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+ 	}
+ 	purple_debug_info("jingle",
+ 			"inserting session with key: %s into table\n", sid);
+@@ -407,27 +407,25 @@ jingle_add_jingle_packet(JingleSession *
+ 			xmlnode_new("jingle");
+ 	gchar *local_jid = jingle_session_get_local_jid(session);
+ 	gchar *remote_jid = jingle_session_get_remote_jid(session);
++	gchar *sid = jingle_session_get_sid(session);
+ 
+ 	xmlnode_set_namespace(jingle, JINGLE);
+ 	xmlnode_set_attrib(jingle, "action", jingle_get_action_name(action));
+ 
+ 	if (jingle_session_is_initiator(session)) {
+-		xmlnode_set_attrib(jingle, "initiator",
+-				jingle_session_get_local_jid(session));
+-		xmlnode_set_attrib(jingle, "responder",
+-				jingle_session_get_remote_jid(session));
++		xmlnode_set_attrib(jingle, "initiator", local_jid);
++		xmlnode_set_attrib(jingle, "responder", remote_jid);
+ 	} else {
+-		xmlnode_set_attrib(jingle, "initiator",
+-				jingle_session_get_remote_jid(session));
+-		xmlnode_set_attrib(jingle, "responder",
+-				jingle_session_get_local_jid(session));
++		xmlnode_set_attrib(jingle, "initiator", remote_jid);
++		xmlnode_set_attrib(jingle, "responder", local_jid);
+ 	}
+ 
++	xmlnode_set_attrib(jingle, "sid", sid);
++
+ 	g_free(local_jid);
+ 	g_free(remote_jid);
++	g_free(sid);
+ 
+-	xmlnode_set_attrib(jingle, "sid", jingle_session_get_sid(session));
+-	
+ 	return jingle;
+ }
+ 
+@@ -504,11 +502,16 @@ void jingle_session_handle_action(Jingle
+ JingleContent *
+ jingle_session_find_content(JingleSession *session, const gchar *name, const gchar *creator)
+ {
+-	GList *iter = session->priv->contents;
++	GList *iter;
++
++	if (name == NULL)
++		return NULL;
++
++	iter = session->priv->contents;
+ 	for (; iter; iter = g_list_next(iter)) {
+ 		JingleContent *content = iter->data;
+ 		gchar *cname = jingle_content_get_name(content);
+-		gboolean result = !strcmp(name, cname);
++		gboolean result = g_str_equal(name, cname);
+ 		g_free(cname);
+ 
+ 		if (creator != NULL) {
+@@ -526,11 +529,16 @@ jingle_session_find_content(JingleSessio
+ JingleContent *
+ jingle_session_find_pending_content(JingleSession *session, const gchar *name, const gchar *creator)
+ {
+-	GList *iter = session->priv->pending_contents;
++	GList *iter;
++
++	if (name == NULL)
++		return NULL;
++
++	iter = session->priv->pending_contents;
+ 	for (; iter; iter = g_list_next(iter)) {
+ 		JingleContent *content = iter->data;
+ 		gchar *cname = jingle_content_get_name(content);
+-		gboolean result = !strcmp(name, cname);
++		gboolean result = g_str_equal(name, cname);
+ 		g_free(cname);
+ 
+ 		if (creator != NULL) {
diff --git a/debian/patches/CVE-2011-4603.patch b/debian/patches/CVE-2011-4603.patch
new file mode 100644
index 0000000..c73a2d0
--- /dev/null
+++ b/debian/patches/CVE-2011-4603.patch
@@ -0,0 +1,29 @@
+Description: fix SILC remote crash
+#
+#
+# patch "libpurple/protocols/silc/ops.c"
+#  from [80bd9a7d3faf9e5ef28438647159fe19847e9839]
+#    to [e828291021afbdd6e6370738aa6224788bf885a3]
+#
+============================================================
+--- pidgin/libpurple/protocols/silc/ops.c	80bd9a7d3faf9e5ef28438647159fe19847e9839
++++ pidgin/libpurple/protocols/silc/ops.c	e828291021afbdd6e6370738aa6224788bf885a3
+@@ -332,10 +332,17 @@ silc_channel_message(SilcClient client, 
+ 	}
+ 
+ 	if (flags & SILC_MESSAGE_FLAG_UTF8) {
+-		tmp = g_markup_escape_text((const char *)message, -1);
++		const char *msg = (const char *)message;
++		char *salvaged = NULL;
++		if (!g_utf8_validate((const char *)message, -1, NULL)) {
++			salvaged = purple_utf8_salvage((const char *)message);
++			msg = salvaged;
++		}
++		tmp = g_markup_escape_text(msg, -1);
+ 		/* Send to Purple */
+ 		serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(convo)),
+ 				 sender->nickname, 0, tmp, time(NULL));
++		g_free(salvaged);
+ 		g_free(tmp);
+ 	}
+ }
diff --git a/debian/patches/series b/debian/patches/series
index f240bda..59a00a0 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -3,3 +3,7 @@ python26.patch
 libnssckbi_path.patch
 baseXX_decode_error_handling_2.patch
 cyrus_sasl_crash.patch
+CVE-2011-3594.patch
+CVE-2011-4601.patch
+CVE-2011-4602.patch
+CVE-2011-4603.patch

Reply to: