comparison libpurple/protocols/jabber/si.c @ 25556:0d7f02640e2b

Make sure that the buffer is large enough to fit DST.ADDR + DST.PORT. This was found in the analysis that Veracode performed on the pidgin codebase.
author Daniel Atallah <daniel.atallah@gmail.com>
date Sat, 02 May 2009 17:43:14 +0000
parents 61e0924de04a
children ab298d237562
comparison
equal deleted inserted replaced
25555:62e619e4957e 25556:0d7f02640e2b
352 jabber_si_xfer_bytestreams_send_read_again_cb(gpointer data, gint source, 352 jabber_si_xfer_bytestreams_send_read_again_cb(gpointer data, gint source,
353 PurpleInputCondition cond) 353 PurpleInputCondition cond)
354 { 354 {
355 PurpleXfer *xfer = data; 355 PurpleXfer *xfer = data;
356 JabberSIXfer *jsx = xfer->data; 356 JabberSIXfer *jsx = xfer->data;
357 char buffer[256]; 357 char buffer[42]; /* 40 for DST.ADDR + 2 bytes for port number*/
358 int len; 358 int len;
359 char *dstaddr, *hash; 359 char *dstaddr, *hash;
360 const char *host; 360 const char *host;
361 361
362 purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_again_cb\n"); 362 purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_again_cb\n");
376 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen); 376 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);
377 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len); 377 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len);
378 jsx->rxlen += len; 378 jsx->rxlen += len;
379 return; 379 return;
380 } else if(jsx->rxqueue[0] != 0x05 || jsx->rxqueue[1] != 0x01 || 380 } else if(jsx->rxqueue[0] != 0x05 || jsx->rxqueue[1] != 0x01 ||
381 jsx->rxqueue[3] != 0x03) { 381 jsx->rxqueue[3] != 0x03 || jsx->rxqueue[4] != 40) {
382 purple_debug_info("jabber", "invalid socks5 stuff\n"); 382 purple_debug_info("jabber", "Invalid socks5 conn req. header[0x%x,0x%x,0x%x,0x%x,0x%x]\n",
383 jsx->rxqueue[0], jsx->rxqueue[1], jsx->rxqueue[2],
384 jsx->rxqueue[3], jsx->rxqueue[4]);
383 purple_input_remove(xfer->watcher); 385 purple_input_remove(xfer->watcher);
384 xfer->watcher = 0; 386 xfer->watcher = 0;
385 close(source); 387 close(source);
386 purple_xfer_cancel_remote(xfer); 388 purple_xfer_cancel_remote(xfer);
387 return; 389 return;
388 } else if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2) { 390 } else if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2) {
389 purple_debug_info("jabber", "reading umpteen more bytes\n"); 391 purple_debug_info("jabber", "reading %u bytes for DST.ADDR + port num (trying to read %u now)\n",
390 len = read(source, buffer, jsx->rxqueue[4] + 5 + 2 - jsx->rxlen); 392 jsx->rxqueue[4] + 2, jsx->rxqueue[4] + 2 - (jsx->rxlen - 5));
393 len = read(source, buffer, jsx->rxqueue[4] + 2 - (jsx->rxlen - 5));
391 if(len < 0 && errno == EAGAIN) 394 if(len < 0 && errno == EAGAIN)
392 return; 395 return;
393 else if(len <= 0) { 396 else if(len <= 0) {
394 purple_input_remove(xfer->watcher); 397 purple_input_remove(xfer->watcher);
395 xfer->watcher = 0; 398 xfer->watcher = 0;
400 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen); 403 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);
401 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len); 404 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len);
402 jsx->rxlen += len; 405 jsx->rxlen += len;
403 } 406 }
404 407
408 /* Have we not read all of DST.ADDR and the following 2-byte port number? */
405 if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2) 409 if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2)
406 return; 410 return;
407 411
408 purple_input_remove(xfer->watcher); 412 purple_input_remove(xfer->watcher);
409 xfer->watcher = 0; 413 xfer->watcher = 0;
413 jsx->js->user->resource, xfer->who); 417 jsx->js->user->resource, xfer->who);
414 418
415 /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */ 419 /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */
416 hash = jabber_calculate_data_sha1sum(dstaddr, strlen(dstaddr)); 420 hash = jabber_calculate_data_sha1sum(dstaddr, strlen(dstaddr));
417 421
418 if(jsx->rxqueue[4] != 40 || strncmp(hash, jsx->rxqueue+5, 40) || 422 if(strncmp(hash, jsx->rxqueue + 5, 40) ||
419 jsx->rxqueue[45] != 0x00 || jsx->rxqueue[46] != 0x00) { 423 jsx->rxqueue[45] != 0x00 || jsx->rxqueue[46] != 0x00) {
420 purple_debug_error("jabber", "someone connected with the wrong info!\n"); 424 if (jsx->rxqueue[45] != 0x00 || jsx->rxqueue[46] != 0x00)
425 purple_debug_error("jabber", "Got SOCKS5 BS conn with the wrong DST.PORT"
426 " (must be 0 - got[0x%x,0x%x]).\n",
427 jsx->rxqueue[45], jsx->rxqueue[46]);
428 else
429 purple_debug_error("jabber", "Got SOCKS5 BS conn with the wrong DST.ADDR"
430 " (expected '%s' - got '%.40s').\n",
431 hash, jsx->rxqueue + 5);
421 close(source); 432 close(source);
422 purple_xfer_cancel_remote(xfer); 433 purple_xfer_cancel_remote(xfer);
423 g_free(hash); 434 g_free(hash);
424 g_free(dstaddr); 435 g_free(dstaddr);
425 return; 436 return;
476 return; 487 return;
477 488
478 purple_input_remove(xfer->watcher); 489 purple_input_remove(xfer->watcher);
479 xfer->watcher = 0; 490 xfer->watcher = 0;
480 491
492 /* If we sent a "Success", wait for a response, otherwise give up and cancel */
481 if (jsx->rxqueue[1] == 0x00) { 493 if (jsx->rxqueue[1] == 0x00) {
482 xfer->watcher = purple_input_add(source, PURPLE_INPUT_READ, 494 xfer->watcher = purple_input_add(source, PURPLE_INPUT_READ,
483 jabber_si_xfer_bytestreams_send_read_again_cb, xfer); 495 jabber_si_xfer_bytestreams_send_read_again_cb, xfer);
484 g_free(jsx->rxqueue); 496 g_free(jsx->rxqueue);
485 jsx->rxqueue = NULL; 497 jsx->rxqueue = NULL;
498 jsx->rxlen = 0;
486 } else { 499 } else {
487 close(source); 500 close(source);
488 purple_xfer_cancel_remote(xfer); 501 purple_xfer_cancel_remote(xfer);
489 } 502 }
490 } 503 }
501 514
502 purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_cb\n"); 515 purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_cb\n");
503 516
504 xfer->fd = source; 517 xfer->fd = source;
505 518
519 /** Try to read the SOCKS5 header */
506 if(jsx->rxlen < 2) { 520 if(jsx->rxlen < 2) {
507 purple_debug_info("jabber", "reading those first two bytes\n"); 521 purple_debug_info("jabber", "reading those first two bytes\n");
508 len = read(source, buffer, 2 - jsx->rxlen); 522 len = read(source, buffer, 2 - jsx->rxlen);
509 if(len < 0 && errno == EAGAIN) 523 if(len < 0 && errno == EAGAIN)
510 return; 524 return;
518 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen); 532 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);
519 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len); 533 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len);
520 jsx->rxlen += len; 534 jsx->rxlen += len;
521 return; 535 return;
522 } else if(jsx->rxlen - 2 < jsx->rxqueue[1]) { 536 } else if(jsx->rxlen - 2 < jsx->rxqueue[1]) {
523 purple_debug_info("jabber", "reading the next umpteen bytes\n"); 537 purple_debug_info("jabber", "reading %u bytes for auth methods (trying to read %u now)\n",
524 len = read(source, buffer, jsx->rxqueue[1] + 2 - jsx->rxlen); 538 jsx->rxqueue[1], jsx->rxqueue[1] - (jsx->rxlen - 2));
539 len = read(source, buffer, jsx->rxqueue[1] - (jsx->rxlen - 2));
525 if(len < 0 && errno == EAGAIN) 540 if(len < 0 && errno == EAGAIN)
526 return; 541 return;
527 else if(len <= 0) { 542 else if(len <= 0) {
528 purple_input_remove(xfer->watcher); 543 purple_input_remove(xfer->watcher);
529 xfer->watcher = 0; 544 xfer->watcher = 0;
534 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen); 549 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);
535 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len); 550 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len);
536 jsx->rxlen += len; 551 jsx->rxlen += len;
537 } 552 }
538 553
554 /* Have we not read all the auth. method bytes? */
539 if(jsx->rxlen -2 < jsx->rxqueue[1]) 555 if(jsx->rxlen -2 < jsx->rxqueue[1])
540 return; 556 return;
541 557
542 purple_input_remove(xfer->watcher); 558 purple_input_remove(xfer->watcher);
543 xfer->watcher = 0; 559 xfer->watcher = 0;