Blame SOURCES/pidgin-2.10.7-CVE-2013-6483.patch

56fe68
diff -up pidgin-2.10.7/libpurple/protocols/jabber/iq.c.CVE-2013-6483 pidgin-2.10.7/libpurple/protocols/jabber/iq.c
56fe68
--- pidgin-2.10.7/libpurple/protocols/jabber/iq.c.CVE-2013-6483	2013-02-11 04:16:52.000000000 -0500
56fe68
+++ pidgin-2.10.7/libpurple/protocols/jabber/iq.c	2014-01-29 10:06:23.876656091 -0500
56fe68
@@ -49,6 +49,18 @@
56fe68
 static GHashTable *iq_handlers = NULL;
56fe68
 static GHashTable *signal_iq_handlers = NULL;
56fe68
 
56fe68
+struct _JabberIqCallbackData {
56fe68
+	JabberIqCallback *callback;
56fe68
+	gpointer data;
56fe68
+	JabberID *to;
56fe68
+};
56fe68
+
56fe68
+void jabber_iq_callbackdata_free(JabberIqCallbackData *jcd)
56fe68
+{
56fe68
+	jabber_id_free(jcd->to);
56fe68
+	g_free(jcd);
56fe68
+}
56fe68
+
56fe68
 JabberIq *jabber_iq_new(JabberStream *js, JabberIqType type)
56fe68
 {
56fe68
 	JabberIq *iq;
56fe68
@@ -98,11 +110,6 @@ JabberIq *jabber_iq_new_query(JabberStre
56fe68
 	return iq;
56fe68
 }
56fe68
 
56fe68
-typedef struct _JabberCallbackData {
56fe68
-	JabberIqCallback *callback;
56fe68
-	gpointer data;
56fe68
-} JabberCallbackData;
56fe68
-
56fe68
 void
56fe68
 jabber_iq_set_callback(JabberIq *iq, JabberIqCallback *callback, gpointer data)
56fe68
 {
56fe68
@@ -125,15 +132,17 @@ void jabber_iq_set_id(JabberIq *iq, cons
56fe68
 
56fe68
 void jabber_iq_send(JabberIq *iq)
56fe68
 {
56fe68
-	JabberCallbackData *jcd;
56fe68
+	JabberIqCallbackData *jcd;
56fe68
 	g_return_if_fail(iq != NULL);
56fe68
 
56fe68
 	jabber_send(iq->js, iq->node);
56fe68
 
56fe68
 	if(iq->id && iq->callback) {
56fe68
-		jcd = g_new0(JabberCallbackData, 1);
56fe68
+		jcd = g_new0(JabberIqCallbackData, 1);
56fe68
 		jcd->callback = iq->callback;
56fe68
 		jcd->data = iq->callback_data;
56fe68
+		jcd->to = jabber_id_new(xmlnode_get_attrib(iq->node, "to"));
56fe68
+
56fe68
 		g_hash_table_insert(iq->js->iq_callbacks, g_strdup(iq->id), jcd);
56fe68
 	}
56fe68
 
56fe68
@@ -276,18 +285,30 @@ void jabber_iq_remove_callback_by_id(Jab
56fe68
 
56fe68
 void jabber_iq_parse(JabberStream *js, xmlnode *packet)
56fe68
 {
56fe68
-	JabberCallbackData *jcd;
56fe68
+	JabberIqCallbackData *jcd;
56fe68
 	xmlnode *child, *error, *x;
56fe68
 	const char *xmlns;
56fe68
 	const char *iq_type, *id, *from;
56fe68
 	JabberIqType type = JABBER_IQ_NONE;
56fe68
 	gboolean signal_return;
56fe68
+	JabberID *from_id;
56fe68
 
56fe68
 	from = xmlnode_get_attrib(packet, "from");
56fe68
 	id = xmlnode_get_attrib(packet, "id");
56fe68
 	iq_type = xmlnode_get_attrib(packet, "type");
56fe68
 
56fe68
 	/*
56fe68
+	 * Ensure the 'from' attribute is valid. No point in handling a stanza
56fe68
+	 * of which we don't understand where it came from.
56fe68
+	 */
56fe68
+	from_id = jabber_id_new(from);
56fe68
+
56fe68
+	if (from && !from_id) {
56fe68
+		purple_debug_error("jabber", "Received an iq with an invalid from: %s\n", from);
56fe68
+		return;
56fe68
+	}
56fe68
+
56fe68
+	/*
56fe68
 	 * child will be either the first tag child or NULL if there is no child.
56fe68
 	 * Historically, we used just the 'query' subchild, but newer XEPs use
56fe68
 	 * differently named children. Grabbing the first child is (for the time
56fe68
@@ -312,6 +333,7 @@ void jabber_iq_parse(JabberStream *js, x
56fe68
 	if (type == JABBER_IQ_NONE) {
56fe68
 		purple_debug_error("jabber", "IQ with invalid type ('%s') - ignoring.\n",
56fe68
 						   iq_type ? iq_type : "(null)");
56fe68
+		jabber_id_free(from_id);
56fe68
 		return;
56fe68
 	}
56fe68
 
56fe68
@@ -342,20 +364,38 @@ void jabber_iq_parse(JabberStream *js, x
56fe68
 			purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n",
56fe68
 			                   iq_type);
56fe68
 
56fe68
+		jabber_id_free(from_id);
56fe68
 		return;
56fe68
 	}
56fe68
 
56fe68
 	signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc),
56fe68
 			"jabber-receiving-iq", js->gc, iq_type, id, from, packet));
56fe68
-	if (signal_return)
56fe68
+	if (signal_return) {
56fe68
+		jabber_id_free(from_id);
56fe68
 		return;
56fe68
+	}
56fe68
 
56fe68
 	/* First, lets see if a special callback got registered */
56fe68
 	if(type == JABBER_IQ_RESULT || type == JABBER_IQ_ERROR) {
56fe68
 		if((jcd = g_hash_table_lookup(js->iq_callbacks, id))) {
56fe68
-			jcd->callback(js, from, type, id, packet, jcd->data);
56fe68
-			jabber_iq_remove_callback_by_id(js, id);
56fe68
-			return;
56fe68
+			if(jabber_id_equal(js, jcd->to, from_id)) {
56fe68
+				jcd->callback(js, from, type, id, packet, jcd->data);
56fe68
+				jabber_iq_remove_callback_by_id(js, id);
56fe68
+				jabber_id_free(from_id);
56fe68
+				return;
56fe68
+			} else {
56fe68
+				char *expected_to;
56fe68
+
56fe68
+				if (jcd->to) {
56fe68
+					expected_to = jabber_id_get_full_jid(jcd->to);
56fe68
+				} else {
56fe68
+					expected_to = jabber_id_get_bare_jid(js->user);
56fe68
+				}
56fe68
+
56fe68
+				purple_debug_error("jabber", "Got a result iq with id %s from %s instead of expected %s!\n", id, from ? from : "(null)", expected_to);
56fe68
+
56fe68
+				g_free(expected_to);
56fe68
+			}
56fe68
 		}
56fe68
 	}
56fe68
 
56fe68
@@ -372,12 +412,15 @@ void jabber_iq_parse(JabberStream *js, x
56fe68
 		if (signal_ref > 0) {
56fe68
 			signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc), "jabber-watched-iq",
56fe68
 					js->gc, iq_type, id, from, child));
56fe68
-			if (signal_return)
56fe68
+			if (signal_return) {
56fe68
+				jabber_id_free(from_id);
56fe68
 				return;
56fe68
+			}
56fe68
 		}
56fe68
 
56fe68
 		if(jih) {
56fe68
 			jih(js, from, type, id, child);
56fe68
+			jabber_id_free(from_id);
56fe68
 			return;
56fe68
 		}
56fe68
 	}
56fe68
@@ -404,6 +447,8 @@ void jabber_iq_parse(JabberStream *js, x
56fe68
 
56fe68
 		jabber_iq_send(iq);
56fe68
 	}
56fe68
+
56fe68
+	jabber_id_free(from_id);
56fe68
 }
56fe68
 
56fe68
 void jabber_iq_register_handler(const char *node, const char *xmlns, JabberIqHandler *handlerfunc)
56fe68
diff -up pidgin-2.10.7/libpurple/protocols/jabber/iq.h.CVE-2013-6483 pidgin-2.10.7/libpurple/protocols/jabber/iq.h
56fe68
--- pidgin-2.10.7/libpurple/protocols/jabber/iq.h.CVE-2013-6483	2013-02-11 04:16:52.000000000 -0500
56fe68
+++ pidgin-2.10.7/libpurple/protocols/jabber/iq.h	2014-01-29 10:06:23.877656064 -0500
56fe68
@@ -36,6 +36,7 @@ typedef enum {
56fe68
 #include "connection.h"
56fe68
 
56fe68
 typedef struct _JabberIq JabberIq;
56fe68
+typedef struct _JabberIqCallbackData  JabberIqCallbackData;
56fe68
 
56fe68
 /**
56fe68
  * A JabberIqHandler is called to process an incoming IQ stanza.
56fe68
@@ -96,6 +97,7 @@ JabberIq *jabber_iq_new_query(JabberStre
56fe68
 
56fe68
 void jabber_iq_parse(JabberStream *js, xmlnode *packet);
56fe68
 
56fe68
+void jabber_iq_callbackdata_free(JabberIqCallbackData *jcd);
56fe68
 void jabber_iq_remove_callback_by_id(JabberStream *js, const char *id);
56fe68
 void jabber_iq_set_callback(JabberIq *iq, JabberIqCallback *cb, gpointer data);
56fe68
 void jabber_iq_set_id(JabberIq *iq, const char *id);
56fe68
diff -up pidgin-2.10.7/libpurple/protocols/jabber/jabber.c.CVE-2013-6483 pidgin-2.10.7/libpurple/protocols/jabber/jabber.c
56fe68
--- pidgin-2.10.7/libpurple/protocols/jabber/jabber.c.CVE-2013-6483	2013-02-11 04:16:52.000000000 -0500
56fe68
+++ pidgin-2.10.7/libpurple/protocols/jabber/jabber.c	2014-01-29 10:06:23.878656039 -0500
56fe68
@@ -988,7 +988,7 @@ jabber_stream_new(PurpleAccount *account
56fe68
 	js->user_jb->subscription |= JABBER_SUB_BOTH;
56fe68
 
56fe68
 	js->iq_callbacks = g_hash_table_new_full(g_str_hash, g_str_equal,
56fe68
-			g_free, g_free);
56fe68
+			g_free, (GDestroyNotify)jabber_iq_callbackdata_free);
56fe68
 	js->chats = g_hash_table_new_full(g_str_hash, g_str_equal,
56fe68
 			g_free, (GDestroyNotify)jabber_chat_free);
56fe68
 	js->next_id = g_random_int();
56fe68
diff -up pidgin-2.10.7/libpurple/protocols/jabber/jutil.c.CVE-2013-6483 pidgin-2.10.7/libpurple/protocols/jabber/jutil.c
56fe68
--- pidgin-2.10.7/libpurple/protocols/jabber/jutil.c.CVE-2013-6483	2013-02-11 04:16:52.000000000 -0500
56fe68
+++ pidgin-2.10.7/libpurple/protocols/jabber/jutil.c	2014-01-29 10:06:23.879656015 -0500
56fe68
@@ -508,6 +508,34 @@ jabber_id_free(JabberID *jid)
56fe68
 	}
56fe68
 }
56fe68
 
56fe68
+
56fe68
+gboolean
56fe68
+jabber_id_equal(JabberStream *js, const JabberID *jid1, const JabberID *jid2)
56fe68
+{
56fe68
+	const JabberID *j1, *j2;
56fe68
+	JabberID *bare_user_jid;
56fe68
+	gboolean equal;
56fe68
+
56fe68
+	/* If an outgoing stanza has no 'to', or an incoming has no 'from',
56fe68
+	 * then those are "the server acting as my account". This function will
56fe68
+	 * handle that correctly.
56fe68
+	 */
56fe68
+	if (!jid1 && !jid2)
56fe68
+		return TRUE;
56fe68
+
56fe68
+	bare_user_jid = jabber_id_to_bare_jid(js->user);
56fe68
+	j1 = jid1 ? jid1 : bare_user_jid;
56fe68
+	j2 = jid2 ? jid2 : bare_user_jid;
56fe68
+
56fe68
+	equal = purple_strequal(j1->node, j2->node) &&
56fe68
+			purple_strequal(j1->domain, j2->domain) &&
56fe68
+			purple_strequal(j1->resource, j2->resource);
56fe68
+
56fe68
+	jabber_id_free(bare_user_jid);
56fe68
+
56fe68
+	return equal;
56fe68
+}
56fe68
+
56fe68
 char *jabber_get_domain(const char *in)
56fe68
 {
56fe68
 	JabberID *jid = jabber_id_new(in);
56fe68
@@ -536,6 +564,17 @@ char *jabber_get_resource(const char *in
56fe68
 	return out;
56fe68
 }
56fe68
 
56fe68
+JabberID *
56fe68
+jabber_id_to_bare_jid(const JabberID *jid)
56fe68
+{
56fe68
+	JabberID *result = g_new0(JabberID, 1);
56fe68
+
56fe68
+	result->node = g_strdup(jid->node);
56fe68
+	result->domain = g_strdup(jid->domain);
56fe68
+
56fe68
+	return result;
56fe68
+}
56fe68
+
56fe68
 char *
56fe68
 jabber_get_bare_jid(const char *in)
56fe68
 {
56fe68
@@ -561,6 +600,19 @@ jabber_id_get_bare_jid(const JabberID *j
56fe68
 	                   NULL);
56fe68
 }
56fe68
 
56fe68
+char *
56fe68
+jabber_id_get_full_jid(const JabberID *jid)
56fe68
+{
56fe68
+	g_return_val_if_fail(jid != NULL, NULL);
56fe68
+
56fe68
+	return g_strconcat(jid->node ? jid->node : "",
56fe68
+	                   jid->node ? "@" : "",
56fe68
+	                   jid->domain,
56fe68
+	                   jid->resource ? "/" : "",
56fe68
+	                   jid->resource ? jid->resource : "",
56fe68
+	                   NULL);
56fe68
+}
56fe68
+
56fe68
 gboolean
56fe68
 jabber_jid_is_domain(const char *jid)
56fe68
 {
56fe68
diff -up pidgin-2.10.7/libpurple/protocols/jabber/jutil.h.CVE-2013-6483 pidgin-2.10.7/libpurple/protocols/jabber/jutil.h
56fe68
--- pidgin-2.10.7/libpurple/protocols/jabber/jutil.h.CVE-2013-6483	2013-02-11 04:16:52.000000000 -0500
56fe68
+++ pidgin-2.10.7/libpurple/protocols/jabber/jutil.h	2014-01-29 10:06:23.879656015 -0500
56fe68
@@ -44,12 +44,23 @@ typedef enum {
56fe68
 #include "jabber.h"
56fe68
 
56fe68
 JabberID* jabber_id_new(const char *str);
56fe68
+
56fe68
+/**
56fe68
+ * Compare two JIDs for equality.
56fe68
+ *
56fe68
+ * Warning: If either JID is NULL then this function uses the user's
56fe68
+ * bare JID, instead!
56fe68
+ */
56fe68
+gboolean jabber_id_equal(JabberStream *js, const JabberID *jid1, const JabberID *jid2);
56fe68
+
56fe68
 void jabber_id_free(JabberID *jid);
56fe68
 
56fe68
 char *jabber_get_domain(const char *jid);
56fe68
 char *jabber_get_resource(const char *jid);
56fe68
 char *jabber_get_bare_jid(const char *jid);
56fe68
 char *jabber_id_get_bare_jid(const JabberID *jid);
56fe68
+char *jabber_id_get_full_jid(const JabberID *jid);
56fe68
+JabberID *jabber_id_to_bare_jid(const JabberID *jid);
56fe68
 
56fe68
 gboolean jabber_jid_is_domain(const char *jid);
56fe68