changeset 23541:54f7e507ea7d

Fix calculating the response to MSN Challenge strings that are an exact multiple of 8 characters long. This seems to happen sporadically when sending OIM's. Also, clean up the mess that is msn_handle_chl. No more 2-tab indent, more consistent whitespace, and broke up some really long lines. Made reference to the wiki on imfreedom.org instead of msnpiki, since it's newer and I re-wrote it ;) References #5379.
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Sun, 22 Jun 2008 01:52:04 +0000
parents 0fc1d2df836e
children 01c3074b2299
files libpurple/protocols/msn/msnutils.c libpurple/protocols/msn/notification.c
diffstat 2 files changed, 83 insertions(+), 91 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/msn/msnutils.c	Sat Jun 21 07:36:16 2008 +0000
+++ b/libpurple/protocols/msn/msnutils.c	Sun Jun 22 01:52:04 2008 +0000
@@ -24,7 +24,8 @@
 #include "msn.h"
 #include "msnutils.h"
 #include "time.h"
-//#include <openssl/md5.h>
+
+#include "cipher.h"
 
 char *rand_guid(void);
 
@@ -465,10 +466,10 @@
 
 	host = g_strdup(str);
 
-	if ((c = strchr(host, ':')) != NULL){
+	if ((c = strchr(host, ':')) != NULL) {
 		*c = '\0';
 		port = atoi(c + 1);
-	}else{
+	} else {
 		port = 1863;
 	}
 
@@ -505,92 +506,102 @@
  ***************************************************************************/
 
 /*
- * Handle MSN Chanllege computation
- *This algorithm reference with http://msnpiki.msnfanatic.com/index.php/MSNP11:Challenges
+ * Handle MSN Challenge computation
+ * This algorithm references
+ *  http://imfreedom.org/wiki/index.php/MSN:NS/Challenges
  */
 #define BUFSIZE	256
 void
 msn_handle_chl(char *input, char *output)
 {
-		PurpleCipher *cipher;
-		PurpleCipherContext *context;
-		char *productKey = MSNP15_WLM_PRODUCT_KEY,
-			 *productID  = MSNP15_WLM_PRODUCT_ID,
-			 *hexChars   = "0123456789abcdef",
-			 buf[BUFSIZE];
-		unsigned char md5Hash[16], *newHash;
-		unsigned int *md5Parts, *chlStringParts, newHashParts[5];
+	PurpleCipher *cipher;
+	PurpleCipherContext *context;
+	const guchar productKey[] = MSNP15_WLM_PRODUCT_KEY;
+	const guchar productID[]  = MSNP15_WLM_PRODUCT_ID;
+	const char hexChars[]     = "0123456789abcdef";
+	char buf[BUFSIZE];
+	unsigned char md5Hash[16];
+	unsigned char *newHash;
+	unsigned int *md5Parts;
+	unsigned int *chlStringParts;
+	unsigned int newHashParts[5];
 
-		long long nHigh=0, nLow=0;
-
-		int i;
+	long long nHigh = 0, nLow = 0;
 
-		/* Create the MD5 hash by using Purple MD5 algorithm*/
-		cipher = purple_ciphers_find_cipher("md5");
-		context = purple_cipher_context_new(cipher, NULL);
+	int len;
+	int i;
 
-		purple_cipher_context_append(context, (const guchar *)input,
-						strlen(input));
-		purple_cipher_context_append(context, (const guchar *)productKey,
-						strlen(productKey));
-		purple_cipher_context_digest(context, sizeof(md5Hash), md5Hash, NULL);
-		purple_cipher_context_destroy(context);
+	/* Create the MD5 hash by using Purple MD5 algorithm */
+	cipher = purple_ciphers_find_cipher("md5");
+	context = purple_cipher_context_new(cipher, NULL);
+
+	purple_cipher_context_append(context, (guchar *)input, strlen(input));
+	purple_cipher_context_append(context, productKey, sizeof(productKey) - 1);
+	purple_cipher_context_digest(context, sizeof(md5Hash), md5Hash, NULL);
+	purple_cipher_context_destroy(context);
 
-		/* Split it into four integers */
-		md5Parts = (unsigned int *)md5Hash;
-		for(i=0; i<4; i++){
-				/* adjust endianess */
-				md5Parts[i] = GUINT_TO_LE(md5Parts[i]);
+	/* Split it into four integers */
+	md5Parts = (unsigned int *)md5Hash;
+	for (i = 0; i < 4; i++) {
+		/* adjust endianess */
+		md5Parts[i] = GUINT_TO_LE(md5Parts[i]);
 
-				/* & each integer with 0x7FFFFFFF          */
-				/* and save one unmodified array for later */
-				newHashParts[i] = md5Parts[i];
-				md5Parts[i] &= 0x7FFFFFFF;
-		}
+		/* & each integer with 0x7FFFFFFF          */
+		/* and save one unmodified array for later */
+		newHashParts[i] = md5Parts[i];
+		md5Parts[i] &= 0x7FFFFFFF;
+	}
 
-		/* make a new string and pad with '0' */
-		snprintf(buf, BUFSIZE-5, "%s%s", input, productID);
-		i = strlen(buf);
-		memset(&buf[i], '0', 8 - (i % 8));
-		buf[i + (8 - (i % 8))]='\0';
-
-		/* split into integers */
-		chlStringParts = (unsigned int *)buf;
+	/* make a new string and pad with '0' to length that's a multiple of 8 */
+	snprintf(buf, BUFSIZE - 5, "%s%s", input, productID);
+	len = strlen(buf);
+	if ((len % 8) != 0) {
+		int fix = 8 - (len % 8);
+		memset(&buf[len], '0', fix);
+		buf[len + fix] = '\0';
+		len += fix;
+	}
 
-		/* this is magic */
-		for (i=0; i<(strlen(buf)/4)-1; i+=2){
-				long long temp;
+	/* split into integers */
+	chlStringParts = (unsigned int *)buf;
 
-				chlStringParts[i]   = GUINT_TO_LE(chlStringParts[i]);
-				chlStringParts[i+1] = GUINT_TO_LE(chlStringParts[i+1]);
+	/* this is magic */
+	for (i = 0; i < (strlen(buf) / 4); i += 2) {
+		long long temp;
 
-				temp=(md5Parts[0] * (((0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF)+nHigh) + md5Parts[1])%0x7FFFFFFF;
-				nHigh=(md5Parts[2] * (((long long)chlStringParts[i+1]+temp) % 0x7FFFFFFF) + md5Parts[3]) % 0x7FFFFFFF;
-				nLow=nLow + nHigh + temp;
-		}
-		nHigh=(nHigh+md5Parts[1]) % 0x7FFFFFFF;
-		nLow=(nLow+md5Parts[3]) % 0x7FFFFFFF;
+		chlStringParts[i] = GUINT_TO_LE(chlStringParts[i]);
+		chlStringParts[i + 1] = GUINT_TO_LE(chlStringParts[i + 1]);
+
+		temp = (0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF;
+		temp = (md5Parts[0] * (temp + nLow) + md5Parts[1]) % 0x7FFFFFFF;
+		nHigh += temp;
 
-		newHashParts[0]^=nHigh;
-		newHashParts[1]^=nLow;
-		newHashParts[2]^=nHigh;
-		newHashParts[3]^=nLow;
+		temp = ((long long)chlStringParts[i + 1] + temp) % 0x7FFFFFFF;
+		nLow = (md5Parts[2] * temp + md5Parts[3]) % 0x7FFFFFFF;
+		nHigh += nLow;
+	}
+	nLow = (nLow + md5Parts[1]) % 0x7FFFFFFF;
+	nHigh = (nHigh + md5Parts[3]) % 0x7FFFFFFF;
 
-		/* adjust endianness */
-		for(i=0; i<4; i++)
-				newHashParts[i] = GUINT_TO_LE(newHashParts[i]);
-
-		/* make a string of the parts */
-		newHash = (unsigned char *)newHashParts;
+	newHashParts[0] ^= nLow;
+	newHashParts[1] ^= nHigh;
+	newHashParts[2] ^= nLow;
+	newHashParts[3] ^= nHigh;
 
-		/* convert to hexadecimal */
-		for (i=0; i<16; i++)
-		{
-				output[i*2]=hexChars[(newHash[i]>>4)&0xF];
-				output[(i*2)+1]=hexChars[newHash[i]&0xF];
-		}
+	/* adjust endianness */
+	for(i = 0; i < 4; i++)
+		newHashParts[i] = GUINT_TO_LE(newHashParts[i]);
+
+	/* make a string of the parts */
+	newHash = (unsigned char *)newHashParts;
 
-		output[32]='\0';
+	/* convert to hexadecimal */
+	for (i = 0; i < 16; i++)
+	{
+		output[i * 2] = hexChars[(newHash[i] >> 4) & 0xF];
+		output[(i * 2) + 1] = hexChars[newHash[i] & 0xF];
+	}
 
-//		purple_debug_info("MSNP14","chl output{%s}\n",output);
+	output[32] = '\0';
 }
+
--- a/libpurple/protocols/msn/notification.c	Sat Jun 21 07:36:16 2008 +0000
+++ b/libpurple/protocols/msn/notification.c	Sun Jun 22 01:52:04 2008 +0000
@@ -523,26 +523,7 @@
 	MsnTransaction *trans;
 	char buf[33];
 
-#if 0
-	cipher = purple_ciphers_find_cipher("md5");
-	context = purple_cipher_context_new(cipher, NULL);
-	purple_cipher_context_append(context, (const guchar *)cmd->params[1],
-							   strlen(cmd->params[1]));
-	challenge_resp = MSNP15_WLM_PRODUCT_KEY;
-
-	purple_cipher_context_append(context, (const guchar *)challenge_resp,
-							   strlen(challenge_resp));
-	purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
-	purple_cipher_context_destroy(context);
-
-	for (i = 0; i < 16; i++)
-	{
-		g_snprintf(buf + (i*2), 3, "%02x", digest[i]);
-	}
-#else
 	msn_handle_chl(cmd->params[1], buf);
-#endif
-//	purple_debug_info("MSNP14","<<challenge:{%s}:{%s}\n",cmd->params[1],buf);
 	trans = msn_transaction_new(cmdproc, "QRY", "%s 32", MSNP15_WLM_PRODUCT_ID);
 
 	msn_transaction_set_payload(trans, buf, 32);