comparison libpurple/protocols/jabber/iq.c @ 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 305fac6af8f9
children bcad7dc4b453 e30e9779e7bf b5052c66701c 45dbea660309
comparison
equal deleted inserted replaced
24301:785db7300ef2 24302:040c66dffbf0
103 iq->callback_data = data; 103 iq->callback_data = data;
104 } 104 }
105 105
106 void jabber_iq_set_id(JabberIq *iq, const char *id) 106 void jabber_iq_set_id(JabberIq *iq, const char *id)
107 { 107 {
108 if(iq->id) 108 g_free(iq->id);
109 g_free(iq->id);
110 109
111 if(id) { 110 if(id) {
112 xmlnode_set_attrib(iq->node, "id", id); 111 xmlnode_set_attrib(iq->node, "id", id);
113 iq->id = g_strdup(id); 112 iq->id = g_strdup(id);
114 } else { 113 } else {
318 query = xmlnode_get_child(packet, "query"); 317 query = xmlnode_get_child(packet, "query");
319 type = xmlnode_get_attrib(packet, "type"); 318 type = xmlnode_get_attrib(packet, "type");
320 from = xmlnode_get_attrib(packet, "from"); 319 from = xmlnode_get_attrib(packet, "from");
321 id = xmlnode_get_attrib(packet, "id"); 320 id = xmlnode_get_attrib(packet, "id");
322 321
322 if(type == NULL || !(!strcmp(type, "get") || !strcmp(type, "set")
323 || !strcmp(type, "result") || !strcmp(type, "error"))) {
324 purple_debug_error("jabber", "IQ with invalid type ('%s') - ignoring.\n",
325 type ? type : "(null)");
326 return;
327 }
328
329 /* All IQs must have an ID, so send an error for a set/get that doesn't */
330 if(!id || !*id) {
331
332 if(!strcmp(type, "set") || !strcmp(type, "get")) {
333 JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR);
334
335 xmlnode_free(iq->node);
336 iq->node = xmlnode_copy(packet);
337 xmlnode_set_attrib(iq->node, "to", from);
338 xmlnode_remove_attrib(iq->node, "from");
339 xmlnode_set_attrib(iq->node, "type", "error");
340 /* This id is clearly not useful, but we must put something there for a valid stanza */
341 iq->id = jabber_get_next_id(js);
342 xmlnode_set_attrib(iq->node, "id", iq->id);
343 error = xmlnode_new_child(iq->node, "error");
344 xmlnode_set_attrib(error, "type", "modify");
345 x = xmlnode_new_child(error, "bad-request");
346 xmlnode_set_namespace(x, "urn:ietf:params:xml:ns:xmpp-stanzas");
347
348 jabber_iq_send(iq);
349 } else
350 purple_debug_error("jabber", "IQ of type '%s' missing id - ignoring.\n", type);
351
352 return;
353 }
354
323 /* First, lets see if a special callback got registered */ 355 /* First, lets see if a special callback got registered */
324 356
325 if(type && (!strcmp(type, "result") || !strcmp(type, "error"))) { 357 if(!strcmp(type, "result") || !strcmp(type, "error")) {
326 if(id && *id && (jcd = g_hash_table_lookup(js->iq_callbacks, id))) { 358 if(id && *id && (jcd = g_hash_table_lookup(js->iq_callbacks, id))) {
327 jcd->callback(js, packet, jcd->data); 359 jcd->callback(js, packet, jcd->data);
328 jabber_iq_remove_callback_by_id(js, id); 360 jabber_iq_remove_callback_by_id(js, id);
329 return; 361 return;
330 } 362 }
331 } 363 }
332 364
333 /* Apparently not, so lets see if we have a pre-defined handler */ 365 /* Apparently not, so lets see if we have a pre-defined handler */
334 366
335 if(type && query && (xmlns = xmlnode_get_namespace(query))) { 367 if(query && (xmlns = xmlnode_get_namespace(query))) {
336 if((jih = g_hash_table_lookup(iq_handlers, xmlns))) { 368 if((jih = g_hash_table_lookup(iq_handlers, xmlns))) {
337 jih(js, packet); 369 jih(js, packet);
338 return; 370 return;
339 } 371 }
340 } 372 }
346 378
347 if(xmlnode_get_child_with_namespace(packet, "new-mail", "google:mail:notify")) { 379 if(xmlnode_get_child_with_namespace(packet, "new-mail", "google:mail:notify")) {
348 jabber_gmail_poke(js, packet); 380 jabber_gmail_poke(js, packet);
349 return; 381 return;
350 } 382 }
351 383
352 purple_debug_info("jabber", "jabber_iq_parse\n"); 384 purple_debug_info("jabber", "jabber_iq_parse\n");
353 385
354 if(xmlnode_get_child_with_namespace(packet, "ping", "urn:xmpp:ping")) { 386 if(xmlnode_get_child_with_namespace(packet, "ping", "urn:xmpp:ping")) {
355 jabber_ping_parse(js, packet); 387 jabber_ping_parse(js, packet);
356 return; 388 return;
360 jabber_data_parse(js, packet); 392 jabber_data_parse(js, packet);
361 return; 393 return;
362 } 394 }
363 395
364 /* If we get here, send the default error reply mandated by XMPP-CORE */ 396 /* If we get here, send the default error reply mandated by XMPP-CORE */
365 if(type && (!strcmp(type, "set") || !strcmp(type, "get"))) { 397 if(!strcmp(type, "set") || !strcmp(type, "get")) {
366 JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR); 398 JabberIq *iq = jabber_iq_new(js, JABBER_IQ_ERROR);
367 399
368 xmlnode_free(iq->node); 400 xmlnode_free(iq->node);
369 iq->node = xmlnode_copy(packet); 401 iq->node = xmlnode_copy(packet);
370 xmlnode_set_attrib(iq->node, "to", from); 402 xmlnode_set_attrib(iq->node, "to", from);