# HG changeset patch # User Elliott Sales de Andrade # Date 1272091312 0 # Node ID a97d60c15e255a52af69a3e400dc8551adf72bf0 # Parent 1664d74b2e69f61a192c60f172d273a0c2bc900d Support old-style Nonce, which should let us use direct connections to aMSN (or msn-pecan?) Refs #247. diff -r 1664d74b2e69 -r a97d60c15e25 libpurple/protocols/msn/directconn.c --- a/libpurple/protocols/msn/directconn.c Sat Apr 24 02:29:34 2010 +0000 +++ b/libpurple/protocols/msn/directconn.c Sat Apr 24 06:41:52 2010 +0000 @@ -49,23 +49,23 @@ static void msn_dc_generate_nonce(MsnDirectConn *dc) { - PurpleCipher *cipher = NULL; - PurpleCipherContext *context = NULL; guint32 *nonce; int i; guchar digest[20]; - cipher = purple_ciphers_find_cipher("sha1"); - g_return_if_fail(cipher != NULL); - nonce = (guint32 *)&dc->nonce; for (i = 0; i < 4; i++) nonce[i] = rand(); - context = purple_cipher_context_new(cipher, NULL); - purple_cipher_context_append(context, dc->nonce, sizeof(dc->nonce)); - purple_cipher_context_digest(context, sizeof(digest), digest, NULL); - purple_cipher_context_destroy(context); + if (dc->nonce_type == DC_NONCE_SHA1) { + PurpleCipher *cipher = purple_ciphers_find_cipher("sha1"); + PurpleCipherContext *context = purple_cipher_context_new(cipher, NULL); + purple_cipher_context_append(context, dc->nonce, sizeof(dc->nonce)); + purple_cipher_context_digest(context, sizeof(digest), digest, NULL); + purple_cipher_context_destroy(context); + } else if (dc->nonce_type == DC_NONCE_PLAIN) { + memcpy(digest, nonce, 16); + } g_sprintf(dc->nonce_hash, "%08X-%04X-%04X-%04X-%08X%04X", @@ -145,6 +145,8 @@ dc->progress = FALSE; //dc->num_calls = 1; + /* TODO: Probably should set this based on buddy caps */ + dc->nonce_type = DC_NONCE_PLAIN; msn_dc_generate_nonce(dc); return dc; @@ -699,11 +701,15 @@ 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); + if (dc->nonce_type == DC_NONCE_SHA1) { + 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); + } else if (dc->nonce_type == DC_NONCE_PLAIN) { + memcpy(digest, nonce, 16); + } g_sprintf(nonce_hash, "%08X-%04X-%04X-%04X-%08X%04X", @@ -1354,13 +1360,14 @@ dc->msg_body = g_strdup_printf( "Bridge: TCPv1\r\n" "Listening: true\r\n" - "Hashed-Nonce: {%s}\r\n" + "%sNonce: {%s}\r\n" "IPv4External-Addrs: %s\r\n" "IPv4External-Port: %d\r\n" "IPv4Internal-Addrs: %s\r\n" "IPv4Internal-Port: %d\r\n" "\r\n", + dc->nonce_type != DC_NONCE_PLAIN ? "Hashed-" : "", dc->nonce_hash, ext_ip, port, @@ -1372,11 +1379,12 @@ dc->msg_body = g_strdup_printf( "Bridge: TCPv1\r\n" "Listening: true\r\n" - "Hashed-Nonce: {%s}\r\n" + "%sNonce: {%s}\r\n" "IPv4External-Addrs: %s\r\n" "IPv4External-Port: %d\r\n" "\r\n", + dc->nonce_type != DC_NONCE_PLAIN ? "Hashed-" : "", dc->nonce_hash, ext_ip, port diff -r 1664d74b2e69 -r a97d60c15e25 libpurple/protocols/msn/directconn.h --- a/libpurple/protocols/msn/directconn.h Sat Apr 24 02:29:34 2010 +0000 +++ b/libpurple/protocols/msn/directconn.h Sat Apr 24 06:41:52 2010 +0000 @@ -53,6 +53,13 @@ } MsnDirectConnProcessResult; +typedef enum +{ + DC_NONCE_PLAIN, /**< No hashing */ + DC_NONCE_SHA1 /**< First 16 bytes of SHA1 of nonce */ + +} MsnDirectConnNonceType; + typedef struct _MsnDirectConnPacket MsnDirectConnPacket; struct _MsnDirectConnPacket { @@ -71,9 +78,10 @@ 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 */ - gchar remote_nonce[37]; /**< The remote side's nonce */ + MsnDirectConnNonceType nonce_type; /**< The type of nonce hashing */ + guchar nonce[16]; /**< The nonce used for 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 */ diff -r 1664d74b2e69 -r a97d60c15e25 libpurple/protocols/msn/slp.c --- a/libpurple/protocols/msn/slp.c Sat Apr 24 02:29:34 2010 +0000 +++ b/libpurple/protocols/msn/slp.c Sat Apr 24 06:41:52 2010 +0000 @@ -631,6 +631,7 @@ /* A direct connection negotiation request */ char *bridges; char *nonce; + MsnDirectConnNonceType ntype; purple_debug_info("msn", "got_invite: transreqbody received\n"); @@ -640,6 +641,12 @@ bridges = get_token(content, "Bridges: ", "\r\n"); nonce = get_token(content, "Hashed-Nonce: {", "}\r\n"); + if (nonce) { + ntype = DC_NONCE_SHA1; + } else { + nonce = get_token(content, "Nonce: {", "}\r\n"); + ntype = DC_NONCE_PLAIN; + } if (nonce && bridges && strstr(bridges, "TCPv1") != NULL) { /* * Ok, the client supports direct TCP connection @@ -648,6 +655,7 @@ MsnDirectConn *dc; dc = msn_dc_new(slpcall); + dc->nonce_type = ntype; strncpy(dc->remote_nonce, nonce, 36); dc->remote_nonce[36] = '\0'; @@ -663,12 +671,20 @@ purple_debug_info("msn", "got_invite: listening failed\n"); - msn_slp_send_ok(slpcall, branch, - "application/x-msnmsgr-transrespbody", - "Bridge: TCPv1\r\n" - "Listening: false\r\n" - "Hashed-Nonce: {00000000-0000-0000-0000-000000000000}\r\n" - "\r\n"); + if (dc->nonce_type != DC_NONCE_PLAIN) + msn_slp_send_ok(slpcall, branch, + "application/x-msnmsgr-transrespbody", + "Bridge: TCPv1\r\n" + "Listening: false\r\n" + "Hashed-Nonce: {00000000-0000-0000-0000-000000000000}\r\n" + "\r\n"); + else + msn_slp_send_ok(slpcall, branch, + "application/x-msnmsgr-transrespbody", + "Bridge: TCPv1\r\n" + "Listening: false\r\n" + "Nonce: {00000000-0000-0000-0000-000000000000}\r\n" + "\r\n"); } else { /* @@ -750,10 +766,11 @@ "Conn-Type: IP-Restrict-NAT\r\n" "UPnPNat: false\r\n" "ICF: false\r\n" - "Hashed-Nonce: {%s}\r\n" + "%sNonce: {%s}\r\n" "\r\n", rand() % G_MAXUINT32, + dc->nonce_type != DC_NONCE_PLAIN ? "Hashed-" : "", dc->nonce_hash ); @@ -768,9 +785,10 @@ "Conn-Type: Direct-Connect\r\n" "UPnPNat: false\r\n" "ICF: false\r\n" - "Hashed-Nonce: {%s}\r\n" + "%sNonce: {%s}\r\n" "\r\n", + dc->nonce_type != DC_NONCE_PLAIN ? "Hashed-" : "", dc->nonce_hash ); }