|
|
56fe68 |
diff -up pidgin-2.10.7/libpurple/protocols/jabber/iq.c.CVE-2013-6483-regression pidgin-2.10.7/libpurple/protocols/jabber/iq.c
|
|
|
56fe68 |
--- pidgin-2.10.7/libpurple/protocols/jabber/iq.c.CVE-2013-6483-regression 2014-02-03 09:49:18.556521925 -0500
|
|
|
56fe68 |
+++ pidgin-2.10.7/libpurple/protocols/jabber/iq.c 2014-02-03 09:49:29.904554588 -0500
|
|
|
56fe68 |
@@ -283,6 +283,52 @@ void jabber_iq_remove_callback_by_id(Jab
|
|
|
56fe68 |
g_hash_table_remove(js->iq_callbacks, id);
|
|
|
56fe68 |
}
|
|
|
56fe68 |
|
|
|
56fe68 |
+/**
|
|
|
56fe68 |
+ * Verify that the 'from' attribute of an IQ reply is a valid match for
|
|
|
56fe68 |
+ * a given IQ request. The expected behavior is outlined in section
|
|
|
56fe68 |
+ * 8.1.2.1 of the XMPP CORE spec (RFC 6120). We consider the reply to
|
|
|
56fe68 |
+ * be a valid match if any of the following is true:
|
|
|
56fe68 |
+ * - Request 'to' matches reply 'from' (including the case where
|
|
|
56fe68 |
+ * neither are set).
|
|
|
56fe68 |
+ * - Request 'to' was empty and reply 'from' is server JID.
|
|
|
56fe68 |
+ * - Request 'to' was empty and reply 'from' is my JID. The spec says
|
|
|
56fe68 |
+ * we should only allow bare JID, but we also allow full JID for
|
|
|
56fe68 |
+ * compatibility with some servers.
|
|
|
56fe68 |
+ *
|
|
|
56fe68 |
+ * These rules should allow valid IQ replies while preventing spoofed
|
|
|
56fe68 |
+ * ones.
|
|
|
56fe68 |
+ *
|
|
|
56fe68 |
+ * For more discussion see the "Spoofing of iq ids and misbehaving
|
|
|
56fe68 |
+ * servers" email thread from January 2014 on the jdev and security
|
|
|
56fe68 |
+ * mailing lists.
|
|
|
56fe68 |
+ *
|
|
|
56fe68 |
+ * @return TRUE if this reply is valid for the given request.
|
|
|
56fe68 |
+ */
|
|
|
56fe68 |
+static gboolean does_reply_from_match_request_to(JabberStream *js, JabberID *to, JabberID *from)
|
|
|
56fe68 |
+{
|
|
|
56fe68 |
+ if (jabber_id_equal(to, from)) {
|
|
|
56fe68 |
+ /* Request 'to' matches reply 'from' */
|
|
|
56fe68 |
+ return TRUE;
|
|
|
56fe68 |
+ }
|
|
|
56fe68 |
+
|
|
|
56fe68 |
+ if (!to && purple_strequal(from->domain, js->user->domain)) {
|
|
|
56fe68 |
+ /* Request 'to' is empty and reply 'from' domain matches our domain */
|
|
|
56fe68 |
+
|
|
|
56fe68 |
+ if (!from->node && !from->resource) {
|
|
|
56fe68 |
+ /* Reply 'from' is server bare JID */
|
|
|
56fe68 |
+ return TRUE;
|
|
|
56fe68 |
+ }
|
|
|
56fe68 |
+
|
|
|
56fe68 |
+ if (purple_strequal(from->node, js->user->node)
|
|
|
56fe68 |
+ && (!from->resource || purple_strequal(from->resource, js->user->resource))) {
|
|
|
56fe68 |
+ /* Reply 'from' is my full or bare JID */
|
|
|
56fe68 |
+ return TRUE;
|
|
|
56fe68 |
+ }
|
|
|
56fe68 |
+ }
|
|
|
56fe68 |
+
|
|
|
56fe68 |
+ return FALSE;
|
|
|
56fe68 |
+}
|
|
|
56fe68 |
+
|
|
|
56fe68 |
void jabber_iq_parse(JabberStream *js, xmlnode *packet)
|
|
|
56fe68 |
{
|
|
|
56fe68 |
JabberIqCallbackData *jcd;
|
|
|
56fe68 |
@@ -377,8 +423,9 @@ void jabber_iq_parse(JabberStream *js, x
|
|
|
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 |
- if(jabber_id_equal(js, jcd->to, from_id)) {
|
|
|
56fe68 |
+ jcd = g_hash_table_lookup(js->iq_callbacks, id);
|
|
|
56fe68 |
+ if (jcd) {
|
|
|
56fe68 |
+ if (does_reply_from_match_request_to(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 |
diff -up pidgin-2.10.7/libpurple/protocols/jabber/jutil.c.CVE-2013-6483-regression pidgin-2.10.7/libpurple/protocols/jabber/jutil.c
|
|
|
56fe68 |
--- pidgin-2.10.7/libpurple/protocols/jabber/jutil.c.CVE-2013-6483-regression 2014-02-03 09:49:18.558521926 -0500
|
|
|
56fe68 |
+++ pidgin-2.10.7/libpurple/protocols/jabber/jutil.c 2014-02-03 09:49:29.904554588 -0500
|
|
|
56fe68 |
@@ -510,30 +510,21 @@ jabber_id_free(JabberID *jid)
|
|
|
56fe68 |
|
|
|
56fe68 |
|
|
|
56fe68 |
gboolean
|
|
|
56fe68 |
-jabber_id_equal(JabberStream *js, const JabberID *jid1, const JabberID *jid2)
|
|
|
56fe68 |
+jabber_id_equal(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 |
+ if (!jid1 && !jid2) {
|
|
|
56fe68 |
+ /* Both are null therefore equal */
|
|
|
56fe68 |
return TRUE;
|
|
|
56fe68 |
+ }
|
|
|
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 |
+ if (!jid1 || !jid2) {
|
|
|
56fe68 |
+ /* One is null, other is non-null, therefore not equal */
|
|
|
56fe68 |
+ return FALSE;
|
|
|
56fe68 |
+ }
|
|
|
56fe68 |
+
|
|
|
56fe68 |
+ return purple_strequal(jid1->node, jid2->node) &&
|
|
|
56fe68 |
+ purple_strequal(jid1->domain, jid2->domain) &&
|
|
|
56fe68 |
+ purple_strequal(jid1->resource, jid2->resource);
|
|
|
56fe68 |
}
|
|
|
56fe68 |
|
|
|
56fe68 |
char *jabber_get_domain(const char *in)
|
|
|
56fe68 |
diff -up pidgin-2.10.7/libpurple/protocols/jabber/jutil.h.CVE-2013-6483-regression pidgin-2.10.7/libpurple/protocols/jabber/jutil.h
|
|
|
56fe68 |
--- pidgin-2.10.7/libpurple/protocols/jabber/jutil.h.CVE-2013-6483-regression 2014-02-03 09:49:18.559521925 -0500
|
|
|
56fe68 |
+++ pidgin-2.10.7/libpurple/protocols/jabber/jutil.h 2014-02-03 09:49:29.904554588 -0500
|
|
|
56fe68 |
@@ -46,12 +46,10 @@ typedef enum {
|
|
|
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 |
+ * Compare two JIDs for equality. In addition to the node and domain,
|
|
|
56fe68 |
+ * the resources of the two JIDs must also be equal (or both absent).
|
|
|
56fe68 |
*/
|
|
|
56fe68 |
-gboolean jabber_id_equal(JabberStream *js, const JabberID *jid1, const JabberID *jid2);
|
|
|
56fe68 |
+gboolean jabber_id_equal(const JabberID *jid1, const JabberID *jid2);
|
|
|
56fe68 |
|
|
|
56fe68 |
void jabber_id_free(JabberID *jid);
|
|
|
56fe68 |
|