changeset 24302:040c66dffbf0

Perform some sanity checking on inbound IQs and send an error / drop as needed. This has the effect of preventing us from sending an invalid response when we get an invalid request (e.g. missing an id). Fixes #7290.
author Daniel Atallah <daniel.atallah@gmail.com>
date Sun, 26 Oct 2008 17:23:40 +0000
parents 785db7300ef2
children 8643ff79db35 a548c565780f
files libpurple/protocols/jabber/iq.c
diffstat 1 files changed, 38 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/jabber/iq.c	Sun Oct 26 00:29:27 2008 +0000
+++ b/libpurple/protocols/jabber/iq.c	Sun Oct 26 17:23:40 2008 +0000
@@ -105,8 +105,7 @@
 
 void jabber_iq_set_id(JabberIq *iq, const char *id)
 {
-	if(iq->id)
-		g_free(iq->id);
+	g_free(iq->id);
 
 	if(id) {
 		xmlnode_set_attrib(iq->node, "id", id);
@@ -320,9 +319,42 @@
 	from = xmlnode_get_attrib(packet, "from");
 	id = xmlnode_get_attrib(packet, "id");
 
+	if(type == NULL || !(!strcmp(type, "get") || !strcmp(type, "set")
+			|| !strcmp(type, "result") || !strcmp(type, "error"))) {
+		purple_debug_error("jabber", "IQ with invalid type ('%s') - ignoring.\n",
+						   type ? type : "(null)");
+		return;
+	}
+
+	/* All IQs must have an ID, so send an error for a set/get that doesn't */
+	if(!id || !*id) {
+
+		if(!strcmp(type, "set") || !strcmp(type, "get")) {
+			JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR);
+
+			xmlnode_free(iq->node);
+			iq->node = xmlnode_copy(packet);
+			xmlnode_set_attrib(iq->node, "to", from);
+			xmlnode_remove_attrib(iq->node, "from");
+			xmlnode_set_attrib(iq->node, "type", "error");
+			/* This id is clearly not useful, but we must put something there for a valid stanza */
+			iq->id = jabber_get_next_id(js);
+			xmlnode_set_attrib(iq->node, "id", iq->id);
+			error = xmlnode_new_child(iq->node, "error");
+			xmlnode_set_attrib(error, "type", "modify");
+			x = xmlnode_new_child(error, "bad-request");
+			xmlnode_set_namespace(x, "urn:ietf:params:xml:ns:xmpp-stanzas");
+
+			jabber_iq_send(iq);
+		} else
+			purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n", type);
+
+		return;
+	}
+
 	/* First, lets see if a special callback got registered */
 
-	if(type && (!strcmp(type, "result") || !strcmp(type, "error"))) {
+	if(!strcmp(type, "result") || !strcmp(type, "error")) {
 		if(id && *id && (jcd = g_hash_table_lookup(js->iq_callbacks, id))) {
 			jcd->callback(js, packet, jcd->data);
 			jabber_iq_remove_callback_by_id(js, id);
@@ -332,7 +364,7 @@
 
 	/* Apparently not, so lets see if we have a pre-defined handler */
 
-	if(type && query && (xmlns = xmlnode_get_namespace(query))) {
+	if(query && (xmlns = xmlnode_get_namespace(query))) {
 		if((jih = g_hash_table_lookup(iq_handlers, xmlns))) {
 			jih(js, packet);
 			return;
@@ -348,7 +380,7 @@
 		jabber_gmail_poke(js, packet);
 		return;
 	}
-	
+
 	purple_debug_info("jabber", "jabber_iq_parse\n");
 
 	if(xmlnode_get_child_with_namespace(packet, "ping", "urn:xmpp:ping")) {
@@ -362,7 +394,7 @@
 	}
 
 	/* If we get here, send the default error reply mandated by XMPP-CORE */
-	if(type && (!strcmp(type, "set") || !strcmp(type, "get"))) {
+	if(!strcmp(type, "set") || !strcmp(type, "get")) {
 		JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR);
 
 		xmlnode_free(iq->node);