changeset 30459:a97d60c15e25

Support old-style Nonce, which should let us use direct connections to aMSN (or msn-pecan?) Refs #247.
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Sat, 24 Apr 2010 06:41:52 +0000
parents 1664d74b2e69
children 0cc4f8651462
files libpurple/protocols/msn/directconn.c libpurple/protocols/msn/directconn.h libpurple/protocols/msn/slp.c
diffstat 3 files changed, 61 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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 */
--- 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
 			);
 		}