pidgin: f018adec: Save remote nonce, and verify we get the...
qulogic at pidgin.im
qulogic at pidgin.im
Fri May 21 18:07:25 EDT 2010
-----------------------------------------------------------------
Revision: f018adec86242720ca1a9930f5c50a409428281f
Ancestor: 062ec4fac7dc62bf2ceb21aa92e70177984219d8
Author: qulogic at pidgin.im
Date: 2010-04-23T22:38:13
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/f018adec86242720ca1a9930f5c50a409428281f
Modified files:
libpurple/protocols/msn/directconn.c
libpurple/protocols/msn/directconn.h
libpurple/protocols/msn/slp.c
ChangeLog:
Save remote nonce, and verify we get the same data when initiating the
direct connection.
Refs #247.
-------------- next part --------------
============================================================
--- libpurple/protocols/msn/directconn.c e4290503029e78917e1037b548a1b0fb8eae02ad
+++ libpurple/protocols/msn/directconn.c 82bbc5b3eab9a009c6cd87d434deb1b5a8d676c7
@@ -76,6 +76,9 @@ msn_dc_generate_nonce(MsnDirectConn *dc)
GUINT32_FROM_BE(*((guint32 *)(digest + 10))),
GUINT16_FROM_BE(*((guint16 *)(digest + 14)))
);
+
+ if (purple_debug_is_verbose())
+ purple_debug_info("msn", "DC %p generated nonce %s\n", dc, dc->nonce_hash);
}
static MsnDirectConnPacket *
@@ -682,6 +685,53 @@ msn_dc_send_handshake_reply(MsnDirectCon
msn_dc_enqueue_packet(dc, p);
}
+static gboolean
+msn_dc_verify_handshake(MsnDirectConn *dc, guint32 packet_length)
+{
+ PurpleCipherContext *context;
+ PurpleCipher *cipher;
+ guchar nonce[16];
+ guchar digest[20];
+ gchar nonce_hash[37];
+
+ if (packet_length != DC_PACKET_HEADER_SIZE)
+ return FALSE;
+
+ memcpy(nonce, dc->in_buffer + 4 + offsetof(MsnDcContext, ack_id), 16);
+
+ cipher = purple_ciphers_find_cipher("sha1");
+ context = purple_cipher_context_new(cipher, NULL);
+ purple_cipher_context_append(context, nonce, sizeof(nonce));
+ purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
+ purple_cipher_context_destroy(context);
+
+ g_sprintf(nonce_hash,
+ "%08X-%04X-%04X-%04X-%08X%04X",
+ GUINT32_FROM_LE(*((guint32 *)(digest + 0))),
+ GUINT16_FROM_LE(*((guint16 *)(digest + 4))),
+ GUINT16_FROM_LE(*((guint16 *)(digest + 6))),
+ GUINT16_FROM_BE(*((guint16 *)(digest + 8))),
+ GUINT32_FROM_BE(*((guint32 *)(digest + 10))),
+ GUINT16_FROM_BE(*((guint16 *)(digest + 14)))
+ );
+
+ if (g_str_equal(dc->remote_nonce, nonce_hash)) {
+ purple_debug_info("msn",
+ "Received nonce %s from buddy request "
+ "and calculated nonce %s from DC attempt. "
+ "Nonces match, allowing direct connection\n",
+ dc->remote_nonce, nonce_hash);
+ return TRUE;
+ } else {
+ purple_debug_warning("msn",
+ "Received nonce %s from buddy request "
+ "and calculated nonce %s from DC attempt. "
+ "Nonces don't match, ignoring direct connection\n",
+ dc->remote_nonce, nonce_hash);
+ return TRUE;
+ }
+}
+
static void
msn_dc_send_packet_cb(MsnDirectConnPacket *p)
{
@@ -727,10 +777,9 @@ msn_dc_process_packet(MsnDirectConn *dc,
break;
case DC_STATE_HANDSHAKE:
- if (packet_length != DC_PACKET_HEADER_SIZE)
+ if (!msn_dc_verify_handshake(dc, packet_length))
return DC_PROCESS_FALLBACK;
- /* TODO: Check! */
msn_dc_send_handshake_reply(dc);
dc->state = DC_STATE_ESTABLISHED;
@@ -739,7 +788,9 @@ msn_dc_process_packet(MsnDirectConn *dc,
break;
case DC_STATE_HANDSHAKE_REPLY:
- /* TODO: Check! */
+ if (!msn_dc_verify_handshake(dc, packet_length))
+ return DC_PROCESS_FALLBACK;
+
dc->state = DC_STATE_ESTABLISHED;
msn_slpcall_session_init(dc->slpcall);
============================================================
--- libpurple/protocols/msn/directconn.h 73642d30b7e86a563f3bc59386d0bea88b1a228e
+++ libpurple/protocols/msn/directconn.h e4fe02d33e840c7e699019d582c66b5624022556
@@ -71,8 +71,9 @@ struct _MsnDirectConn
char *msg_body; /**< The body of message sent by send_connection_info_msg_cb */
MsnSlpMessage *prev_ack; /**< The saved SLP ACK message */
- guchar nonce[16]; /**< The nonce used for direct connection handshake */
- gchar nonce_hash[37]; /**< The hash of nonce */
+ guchar nonce[16]; /**< The nonce used for direct connection handshake */
+ gchar nonce_hash[37]; /**< The hash of nonce */
+ gchar remote_nonce[37]; /**< The remote side's nonce */
PurpleNetworkListenData *listen_data; /**< The pending socket creation request */
PurpleProxyConnectData *connect_data; /**< The pending connection attempt */
============================================================
--- libpurple/protocols/msn/slp.c ebe00f263437a3cd40b2e493ba049772f6562718
+++ libpurple/protocols/msn/slp.c ec788a4998b43739d5897b7b06df54b42c0c261d
@@ -281,6 +281,7 @@ msn_slp_process_transresp(MsnSlpCall *sl
{
/* A direct connection negotiation response */
char *bridge;
+ char *nonce;
MsnDirectConn *dc = slpcall->slplink->dc;
gboolean result = FALSE;
@@ -290,9 +291,13 @@ msn_slp_process_transresp(MsnSlpCall *sl
g_return_val_if_fail(dc->state == DC_STATE_CLOSED, FALSE);
bridge = get_token(content, "Bridge: ", "\r\n");
- if (bridge && !strcmp(bridge, "TCPv1")) {
+ nonce = get_token(content, "Hashed-Nonce: {", "}\r\n");
+ if (nonce && bridge && !strcmp(bridge, "TCPv1")) {
/* Ok, the client supports direct TCP connection */
+ strncpy(dc->remote_nonce, nonce, 36);
+ dc->remote_nonce[36] = '\0';
+
if (dc->listen_data != NULL || dc->listenfd != -1) {
if (dc->listen_data != NULL) {
/*
@@ -377,6 +382,7 @@ msn_slp_process_transresp(MsnSlpCall *sl
*/
}
+ g_free(nonce);
g_free(bridge);
return result;
@@ -624,6 +630,7 @@ got_invite(MsnSlpCall *slpcall,
{
/* A direct connection negotiation request */
char *bridges;
+ char *nonce;
purple_debug_info("msn", "got_invite: transreqbody received\n");
@@ -632,7 +639,8 @@ got_invite(MsnSlpCall *slpcall,
return;
bridges = get_token(content, "Bridges: ", "\r\n");
- if (bridges && strstr(bridges, "TCPv1") != NULL) {
+ nonce = get_token(content, "Hashed-Nonce: {", "}\r\n");
+ if (nonce && bridges && strstr(bridges, "TCPv1") != NULL) {
/*
* Ok, the client supports direct TCP connection
* Try to create a listening port
@@ -640,6 +648,8 @@ got_invite(MsnSlpCall *slpcall,
MsnDirectConn *dc;
dc = msn_dc_new(slpcall);
+ strncpy(dc->remote_nonce, nonce, 36);
+ dc->remote_nonce[36] = '\0';
dc->listen_data = purple_network_listen_range(
0, 0,
@@ -680,6 +690,7 @@ got_invite(MsnSlpCall *slpcall,
*/
}
+ g_free(nonce);
g_free(bridges);
}
else if (!strcmp(type, "application/x-msnmsgr-transrespbody"))
More information about the Commits
mailing list