Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 855925 Details for
Bug 1056978
CVE-2013-6483 pidgin: Possible spoofing using iq replies in XMPP protocol plugin
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Local copy of patch
CVE-2013-6483.diff (text/plain), 9.68 KB, created by
Huzaifa S. Sidhpurwala
on 2014-01-27 06:14:25 UTC
(
hide
)
Description:
Local copy of patch
Filename:
MIME Type:
Creator:
Huzaifa S. Sidhpurwala
Created:
2014-01-27 06:14:25 UTC
Size:
9.68 KB
patch
obsolete
>changeset: 35192:93d4bff19574 >branch: release-2.x.y >user: Mark Doliner <mark@kingant.net> >date: Sun Jan 12 22:51:33 2014 -0800 >summary: Prevent spoofing of iq replies by verifying that the 'from' address > >diff -r ed1f9a0c0979 -r 93d4bff19574 ChangeLog >--- a/ChangeLog Sun Jan 12 19:29:36 2014 -0800 >+++ b/ChangeLog Sun Jan 12 22:51:33 2014 -0800 >@@ -69,6 +69,10 @@ version 2.10.8: > (Discovered by Sourcefire VRT) (CVE-2014-NNNN) > > XMPP: >+ * Prevent spoofing of iq replies by verifying that the 'from' address >+ matches the 'to' address of the iq request. (Discovered by Fabian >+ Yamaguchi and Christian Wressnegger of the University of Goettingen) >+ (CVE-2014-NNNN) > * Fix possible crash or other erratic behavior when selecting a very > small file for your own buddy icon. > * Fix crash if the user tries to initiate a voice/video session with a >diff -r ed1f9a0c0979 -r 93d4bff19574 libpurple/protocols/jabber/iq.c >--- a/libpurple/protocols/jabber/iq.c Sun Jan 12 19:29:36 2014 -0800 >+++ b/libpurple/protocols/jabber/iq.c Sun Jan 12 22:51:33 2014 -0800 >@@ -49,6 +49,18 @@ > static GHashTable *iq_handlers = NULL; > static GHashTable *signal_iq_handlers = NULL; > >+struct _JabberIqCallbackData { >+ JabberIqCallback *callback; >+ gpointer data; >+ JabberID *to; >+}; >+ >+void jabber_iq_callbackdata_free(JabberIqCallbackData *jcd) >+{ >+ jabber_id_free(jcd->to); >+ g_free(jcd); >+} >+ > JabberIq *jabber_iq_new(JabberStream *js, JabberIqType type) > { > JabberIq *iq; >@@ -98,11 +110,6 @@ JabberIq *jabber_iq_new_query(JabberStre > return iq; > } > >-typedef struct _JabberCallbackData { >- JabberIqCallback *callback; >- gpointer data; >-} JabberCallbackData; >- > void > jabber_iq_set_callback(JabberIq *iq, JabberIqCallback *callback, gpointer data) > { >@@ -125,15 +132,17 @@ void jabber_iq_set_id(JabberIq *iq, cons > > void jabber_iq_send(JabberIq *iq) > { >- JabberCallbackData *jcd; >+ JabberIqCallbackData *jcd; > g_return_if_fail(iq != NULL); > > jabber_send(iq->js, iq->node); > > if(iq->id && iq->callback) { >- jcd = g_new0(JabberCallbackData, 1); >+ jcd = g_new0(JabberIqCallbackData, 1); > jcd->callback = iq->callback; > jcd->data = iq->callback_data; >+ jcd->to = jabber_id_new(xmlnode_get_attrib(iq->node, "to")); >+ > g_hash_table_insert(iq->js->iq_callbacks, g_strdup(iq->id), jcd); > } > >@@ -276,18 +285,30 @@ void jabber_iq_remove_callback_by_id(Jab > > void jabber_iq_parse(JabberStream *js, xmlnode *packet) > { >- JabberCallbackData *jcd; >+ JabberIqCallbackData *jcd; > xmlnode *child, *error, *x; > const char *xmlns; > const char *iq_type, *id, *from; > JabberIqType type = JABBER_IQ_NONE; > gboolean signal_return; >+ JabberID *from_id; > > from = xmlnode_get_attrib(packet, "from"); > id = xmlnode_get_attrib(packet, "id"); > iq_type = xmlnode_get_attrib(packet, "type"); > > /* >+ * Ensure the 'from' attribute is valid. No point in handling a stanza >+ * of which we don't understand where it came from. >+ */ >+ from_id = jabber_id_new(from); >+ >+ if (from && !from_id) { >+ purple_debug_error("jabber", "Received an iq with an invalid from: %s\n", from); >+ return; >+ } >+ >+ /* > * child will be either the first tag child or NULL if there is no child. > * Historically, we used just the 'query' subchild, but newer XEPs use > * differently named children. Grabbing the first child is (for the time >@@ -312,6 +333,7 @@ void jabber_iq_parse(JabberStream *js, x > if (type == JABBER_IQ_NONE) { > purple_debug_error("jabber", "IQ with invalid type ('%s') - ignoring.\n", > iq_type ? iq_type : "(null)"); >+ jabber_id_free(from_id); > return; > } > >@@ -342,20 +364,38 @@ void jabber_iq_parse(JabberStream *js, x > purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n", > iq_type); > >+ jabber_id_free(from_id); > return; > } > > signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc), > "jabber-receiving-iq", js->gc, iq_type, id, from, packet)); >- if (signal_return) >+ if (signal_return) { >+ jabber_id_free(from_id); > return; >+ } > > /* First, lets see if a special callback got registered */ > if(type == JABBER_IQ_RESULT || type == JABBER_IQ_ERROR) { > if((jcd = g_hash_table_lookup(js->iq_callbacks, id))) { >- jcd->callback(js, from, type, id, packet, jcd->data); >- jabber_iq_remove_callback_by_id(js, id); >- return; >+ if(jabber_id_equal(js, jcd->to, from_id)) { >+ jcd->callback(js, from, type, id, packet, jcd->data); >+ jabber_iq_remove_callback_by_id(js, id); >+ jabber_id_free(from_id); >+ return; >+ } else { >+ char *expected_to; >+ >+ if (jcd->to) { >+ expected_to = jabber_id_get_full_jid(jcd->to); >+ } else { >+ expected_to = jabber_id_get_bare_jid(js->user); >+ } >+ >+ purple_debug_error("jabber", "Got a result iq with id %s from %s instead of expected %s!\n", id, from ? from : "(null)", expected_to); >+ >+ g_free(expected_to); >+ } > } > } > >@@ -372,12 +412,15 @@ void jabber_iq_parse(JabberStream *js, x > if (signal_ref > 0) { > signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(purple_connection_get_prpl(js->gc), "jabber-watched-iq", > js->gc, iq_type, id, from, child)); >- if (signal_return) >+ if (signal_return) { >+ jabber_id_free(from_id); > return; >+ } > } > > if(jih) { > jih(js, from, type, id, child); >+ jabber_id_free(from_id); > return; > } > } >@@ -404,6 +447,8 @@ void jabber_iq_parse(JabberStream *js, x > > jabber_iq_send(iq); > } >+ >+ jabber_id_free(from_id); > } > > void jabber_iq_register_handler(const char *node, const char *xmlns, JabberIqHandler *handlerfunc) >diff -r ed1f9a0c0979 -r 93d4bff19574 libpurple/protocols/jabber/iq.h >--- a/libpurple/protocols/jabber/iq.h Sun Jan 12 19:29:36 2014 -0800 >+++ b/libpurple/protocols/jabber/iq.h Sun Jan 12 22:51:33 2014 -0800 >@@ -36,6 +36,7 @@ typedef enum { > #include "connection.h" > > typedef struct _JabberIq JabberIq; >+typedef struct _JabberIqCallbackData JabberIqCallbackData; > > /** > * A JabberIqHandler is called to process an incoming IQ stanza. >@@ -96,6 +97,7 @@ JabberIq *jabber_iq_new_query(JabberStre > > void jabber_iq_parse(JabberStream *js, xmlnode *packet); > >+void jabber_iq_callbackdata_free(JabberIqCallbackData *jcd); > void jabber_iq_remove_callback_by_id(JabberStream *js, const char *id); > void jabber_iq_set_callback(JabberIq *iq, JabberIqCallback *cb, gpointer data); > void jabber_iq_set_id(JabberIq *iq, const char *id); >diff -r ed1f9a0c0979 -r 93d4bff19574 libpurple/protocols/jabber/jabber.c >--- a/libpurple/protocols/jabber/jabber.c Sun Jan 12 19:29:36 2014 -0800 >+++ b/libpurple/protocols/jabber/jabber.c Sun Jan 12 22:51:33 2014 -0800 >@@ -988,7 +988,7 @@ jabber_stream_new(PurpleAccount *account > js->user_jb->subscription |= JABBER_SUB_BOTH; > > js->iq_callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, >- g_free, g_free); >+ g_free, (GDestroyNotify)jabber_iq_callbackdata_free); > js->chats = g_hash_table_new_full(g_str_hash, g_str_equal, > g_free, (GDestroyNotify)jabber_chat_free); > js->next_id = g_random_int(); >diff -r ed1f9a0c0979 -r 93d4bff19574 libpurple/protocols/jabber/jutil.c >--- a/libpurple/protocols/jabber/jutil.c Sun Jan 12 19:29:36 2014 -0800 >+++ b/libpurple/protocols/jabber/jutil.c Sun Jan 12 22:51:33 2014 -0800 >@@ -508,6 +508,34 @@ jabber_id_free(JabberID *jid) > } > } > >+ >+gboolean >+jabber_id_equal(JabberStream *js, const JabberID *jid1, const JabberID *jid2) >+{ >+ const JabberID *j1, *j2; >+ JabberID *bare_user_jid; >+ gboolean equal; >+ >+ /* If an outgoing stanza has no 'to', or an incoming has no 'from', >+ * then those are "the server acting as my account". This function will >+ * handle that correctly. >+ */ >+ if (!jid1 && !jid2) >+ return TRUE; >+ >+ bare_user_jid = jabber_id_to_bare_jid(js->user); >+ j1 = jid1 ? jid1 : bare_user_jid; >+ j2 = jid2 ? jid2 : bare_user_jid; >+ >+ equal = purple_strequal(j1->node, j2->node) && >+ purple_strequal(j1->domain, j2->domain) && >+ purple_strequal(j1->resource, j2->resource); >+ >+ jabber_id_free(bare_user_jid); >+ >+ return equal; >+} >+ > char *jabber_get_domain(const char *in) > { > JabberID *jid = jabber_id_new(in); >@@ -536,6 +564,17 @@ char *jabber_get_resource(const char *in > return out; > } > >+JabberID * >+jabber_id_to_bare_jid(const JabberID *jid) >+{ >+ JabberID *result = g_new0(JabberID, 1); >+ >+ result->node = g_strdup(jid->node); >+ result->domain = g_strdup(jid->domain); >+ >+ return result; >+} >+ > char * > jabber_get_bare_jid(const char *in) > { >@@ -561,6 +600,19 @@ jabber_id_get_bare_jid(const JabberID *j > NULL); > } > >+char * >+jabber_id_get_full_jid(const JabberID *jid) >+{ >+ g_return_val_if_fail(jid != NULL, NULL); >+ >+ return g_strconcat(jid->node ? jid->node : "", >+ jid->node ? "@" : "", >+ jid->domain, >+ jid->resource ? "/" : "", >+ jid->resource ? jid->resource : "", >+ NULL); >+} >+ > gboolean > jabber_jid_is_domain(const char *jid) > { >diff -r ed1f9a0c0979 -r 93d4bff19574 libpurple/protocols/jabber/jutil.h >--- a/libpurple/protocols/jabber/jutil.h Sun Jan 12 19:29:36 2014 -0800 >+++ b/libpurple/protocols/jabber/jutil.h Sun Jan 12 22:51:33 2014 -0800 >@@ -44,12 +44,23 @@ typedef enum { > #include "jabber.h" > > JabberID* jabber_id_new(const char *str); >+ >+/** >+ * Compare two JIDs for equality. >+ * >+ * Warning: If either JID is NULL then this function uses the user's >+ * bare JID, instead! >+ */ >+gboolean jabber_id_equal(JabberStream *js, const JabberID *jid1, const JabberID *jid2); >+ > void jabber_id_free(JabberID *jid); > > char *jabber_get_domain(const char *jid); > char *jabber_get_resource(const char *jid); > char *jabber_get_bare_jid(const char *jid); > char *jabber_id_get_bare_jid(const JabberID *jid); >+char *jabber_id_get_full_jid(const JabberID *jid); >+JabberID *jabber_id_to_bare_jid(const JabberID *jid); > > gboolean jabber_jid_is_domain(const char *jid); > >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 1056978
: 855925