|
|
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 |
|