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