comparison libpurple/protocols/msn/directconn.c @ 31088:b55b3d34846c

A direct connection really has no need of the whole P2P packet header, and there's no need to shoehorn the nonce negotiation into one either.
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Tue, 04 Jan 2011 09:12:59 +0000
parents a8cc50c2279f
children 089a9825076c
comparison
equal deleted inserted replaced
31087:a46a737efbe3 31088:b55b3d34846c
25 #include "internal.h" 25 #include "internal.h"
26 #include "cipher.h" 26 #include "cipher.h"
27 #include "debug.h" 27 #include "debug.h"
28 28
29 #include "msn.h" 29 #include "msn.h"
30 #include "msnutils.h"
30 #include "directconn.h" 31 #include "directconn.h"
31 32
32 #include "slp.h" 33 #include "slp.h"
33 #include "slpmsg.h" 34 #include "slpmsg.h"
34 #include "p2p.h" 35 #include "p2p.h"
440 memcpy(p->data, "foo\0", 4); 441 memcpy(p->data, "foo\0", 4);
441 442
442 msn_dc_enqueue_packet(dc, p); 443 msn_dc_enqueue_packet(dc, p);
443 } 444 }
444 445
445 static void 446 #if 0 /* We don't actually need this */
446 msn_dc_send_handshake_with_nonce(MsnDirectConn *dc, MsnDirectConnPacket *p) 447 typedef struct {
447 { 448 guint32 null;
448 const gchar *h; 449 guint32 id;
449 450 guint32 null[5];
450 h = msn_p2p_header_to_wire(&dc->header); 451 guint32 flags;
451 452 guint8 nonce[16];
452 memcpy(p->data, h, P2P_PACKET_HEADER_SIZE); 453 } MsnDirectConnNoncePacket;
453 454 #endif
454 memcpy(p->data + P2P_HEADER_ACK_ID_OFFSET, dc->nonce, 16); 455 #define DC_NONCE_PACKET_SIZE (8 * 4 + 16)
456 #define DC_NONCE_PACKET_NONCE (8 * 4)
457
458 static void
459 msn_dc_send_handshake(MsnDirectConn *dc)
460 {
461 MsnDirectConnPacket *p;
462 gchar *h;
463
464 p = msn_dc_new_packet(DC_NONCE_PACKET_SIZE);
465 h = (gchar *)p->data;
466
467 msn_push32le(h, 0); /* NUL */
468
469 msn_push32le(h, dc->slpcall->slplink->slp_seq_id++);
470
471 /* More NUL stuff */
472 msn_push64le(h, 0);
473 msn_push64le(h, 0);
474 msn_push32le(h, 0);
475
476 /* Flags */
477 msn_push32le(h, P2P_DC_HANDSHAKE);
478
479 /* The real Nonce, yay! */
480 memcpy(h, dc->nonce, 16);
455 481
456 msn_dc_enqueue_packet(dc, p); 482 msn_dc_enqueue_packet(dc, p);
457 }
458
459 static void
460 msn_dc_send_handshake(MsnDirectConn *dc)
461 {
462 MsnDirectConnPacket *p;
463
464 p = msn_dc_new_packet(P2P_PACKET_HEADER_SIZE);
465
466 dc->header.session_id = 0;
467 dc->header.id = dc->slpcall->slplink->slp_seq_id++;
468 dc->header.offset = 0;
469 dc->header.total_size = 0;
470 dc->header.length = 0;
471 dc->header.flags = 0x100;
472
473 msn_dc_send_handshake_with_nonce(dc, p);
474 }
475
476 static void
477 msn_dc_send_handshake_reply(MsnDirectConn *dc)
478 {
479 MsnDirectConnPacket *p;
480
481 p = msn_dc_new_packet(P2P_PACKET_HEADER_SIZE);
482
483 dc->header.id = dc->slpcall->slplink->slp_seq_id++;
484 dc->header.length = 0;
485
486 msn_dc_send_handshake_with_nonce(dc, p);
487 } 483 }
488 484
489 static gboolean 485 static gboolean
490 msn_dc_verify_handshake(MsnDirectConn *dc, guint32 packet_length) 486 msn_dc_verify_handshake(MsnDirectConn *dc, guint32 packet_length)
491 { 487 {
492 guchar nonce[16]; 488 guchar nonce[16];
493 gchar nonce_hash[37]; 489 gchar nonce_hash[37];
494 490
495 if (packet_length != P2P_PACKET_HEADER_SIZE) 491 if (packet_length != DC_NONCE_PACKET_SIZE)
496 return FALSE; 492 return FALSE;
497 493
498 memcpy(nonce, dc->in_buffer + 4 + P2P_HEADER_ACK_ID_OFFSET, 16); 494 memcpy(nonce, dc->in_buffer + 4 + DC_NONCE_PACKET_NONCE, 16);
499 495
500 if (dc->nonce_type == DC_NONCE_PLAIN) { 496 if (dc->nonce_type == DC_NONCE_PLAIN) {
501 if (memcmp(dc->nonce, nonce, 16) == 0) { 497 if (memcmp(dc->nonce, nonce, 16) == 0) {
502 purple_debug_info("msn", 498 purple_debug_info("msn",
503 "Nonce from buddy request and nonce from DC attempt match, " 499 "Nonce from buddy request and nonce from DC attempt match, "
578 574
579 case DC_STATE_HANDSHAKE: 575 case DC_STATE_HANDSHAKE:
580 if (!msn_dc_verify_handshake(dc, packet_length)) 576 if (!msn_dc_verify_handshake(dc, packet_length))
581 return DC_PROCESS_FALLBACK; 577 return DC_PROCESS_FALLBACK;
582 578
583 msn_dc_send_handshake_reply(dc); 579 msn_dc_send_handshake(dc);
584 dc->state = DC_STATE_ESTABLISHED; 580 dc->state = DC_STATE_ESTABLISHED;
585 581
586 msn_slpcall_session_init(dc->slpcall); 582 msn_slpcall_session_init(dc->slpcall);
587 dc->slpcall = NULL; 583 dc->slpcall = NULL;
588 break; 584 break;
593 589
594 dc->state = DC_STATE_ESTABLISHED; 590 dc->state = DC_STATE_ESTABLISHED;
595 591
596 msn_slpcall_session_init(dc->slpcall); 592 msn_slpcall_session_init(dc->slpcall);
597 dc->slpcall = NULL; 593 dc->slpcall = NULL;
594 msn_dc_send_foo(dc);
598 break; 595 break;
599 596
600 case DC_STATE_ESTABLISHED: 597 case DC_STATE_ESTABLISHED:
601 598 if (packet_length) {
602 if (dc->header.length) { 599 part = msn_slpmsgpart_new_from_data(dc->in_buffer + 4, packet_length);
603 part = msn_slpmsgpart_new_from_data(dc->in_buffer + 4, dc->header.length);
604 if (part) { 600 if (part) {
605 msn_slplink_process_msg(dc->slplink, part); 601 msn_slplink_process_msg(dc->slplink, part);
606 msn_slpmsgpart_unref(part); 602 msn_slpmsgpart_unref(part);
607 } 603 }
608 } 604 }
673 } 669 }
674 670
675 /* Wait for the whole packet to arrive */ 671 /* Wait for the whole packet to arrive */
676 if (dc->in_pos < 4 + packet_length) 672 if (dc->in_pos < 4 + packet_length)
677 return; 673 return;
678
679 if (dc->state != DC_STATE_FOO && packet_length >= P2P_PACKET_HEADER_SIZE) {
680 MsnP2PHeader *context;
681
682 /* Skip packet size */
683 context = msn_p2p_header_from_wire(dc->in_buffer + 4);
684 memcpy(&dc->header, context, P2P_PACKET_HEADER_SIZE);
685 g_free(context);
686 }
687 674
688 switch (msn_dc_process_packet(dc, packet_length)) { 675 switch (msn_dc_process_packet(dc, packet_length)) {
689 case DC_PROCESS_CLOSE: 676 case DC_PROCESS_CLOSE:
690 return; 677 return;
691 678