diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2010-03-20 13:56:27 +0000 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2010-03-20 13:56:27 +0000 |
commit | 21029d0fe2b7b11512d2cc67495d590e9df53f85 (patch) | |
tree | fba3c1a966355572d9dddeb91827d858b746625c /protocols | |
parent | 0baed0da940c0d82280a5674d7fa8ad06d449384 (diff) |
Add MSNP11 challenge code which I'll need for doing this SOAP stuff.
Diffstat (limited to 'protocols')
-rw-r--r-- | protocols/msn/msn.h | 7 | ||||
-rw-r--r-- | protocols/msn/msn_util.c | 96 |
2 files changed, 101 insertions, 2 deletions
diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 84914bc3..4799e226 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2010 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module */ @@ -40,6 +40,10 @@ #define QRY_NAME "msmsgs@msnmsgr.com" #define QRY_CODE "Q1P7W2E4J9R8U3S5" +/* This should be MSN Messenger 7.0.0813 */ +#define MSNP11_PROD_KEY "CFHUR$52U_{VIX5T" +#define MSNP11_PROD_ID "PROD0101{0RM?UBW" + #define MSN_SB_NEW -24062002 #define MSN_MESSAGE_HEADERS "MIME-Version: 1.0\r\n" \ @@ -160,6 +164,7 @@ char **msn_linesplit( char *line ); int msn_handler( struct msn_handler_data *h ); char *msn_http_encode( const char *input ); void msn_msgq_purge( struct im_connection *ic, GSList **list ); +char *msn_p11_challenge( char *challenge ); /* tables.c */ const struct msn_away_state *msn_away_state_by_number( int number ); diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 668a8b8a..59363439 100644 --- a/protocols/msn/msn_util.c +++ b/protocols/msn/msn_util.c @@ -1,7 +1,7 @@ /********************************************************************\ * BitlBee -- An IRC to other IM-networks gateway * * * - * Copyright 2002-2004 Wilmer van der Gaast and others * + * Copyright 2002-2010 Wilmer van der Gaast and others * \********************************************************************/ /* MSN module - Miscellaneous utilities */ @@ -25,6 +25,7 @@ #include "nogaim.h" #include "msn.h" +#include "md5.h" #include <ctype.h> int msn_write( struct im_connection *ic, char *s, int len ) @@ -376,3 +377,96 @@ void msn_msgq_purge( struct im_connection *ic, GSList **list ) imcb_log( ic, "%s", ret->str ); g_string_free( ret, TRUE ); } + +unsigned int little_endian( unsigned int dw ) +{ +#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN + return dw; +#else + /* We're still not sure if this machine is big endian since the + constants above are not that portable. Don't swap bytes, just + force-compose a 32-bit little endian integer. */ + unsigned int ret = 0, i; + char *dst = (char*) (&ret + 1); + + for (i = 0; i < 4; i ++) + { + *(--dst) = dw >> 24; + dw <<= 8; + } + + return ret; +#endif +} + +/* Copied and heavily modified from http://tmsnc.sourceforge.net/chl.c */ + +char *msn_p11_challenge( char *challenge ) +{ + char *output, buf[256]; + md5_state_t md5c; + unsigned char md5Hash[16], *newHash; + unsigned int *md5Parts, *chlStringParts, newHashParts[5]; + long long nHigh = 0, nLow = 0; + int i, n; + + /* Create the MD5 hash */ + md5_init(&md5c); + md5_append(&md5c, (unsigned char*) challenge, strlen(challenge)); + md5_append(&md5c, (unsigned char*) MSNP11_PROD_KEY, strlen(MSNP11_PROD_KEY)); + md5_finish(&md5c, md5Hash); + + /* Split it into four integers */ + md5Parts = (unsigned int *)md5Hash; + for (i = 0; i < 4; i ++) + { + md5Parts[i] = little_endian(md5Parts[i]); + + /* & 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' */ + n = g_snprintf(buf, sizeof(buf)-5, "%s%s00000000", challenge, MSNP11_PROD_ID); + /* truncate at an 8-byte boundary */ + buf[n&=~7] = '\0'; + + /* split into integers */ + chlStringParts = (unsigned int *)buf; + + /* this is magic */ + for (i = 0; i < (n / 4) - 1; i += 2) + { + long long temp; + + chlStringParts[i] = little_endian(chlStringParts[i]); + chlStringParts[i+1] = little_endian(chlStringParts[i+1]); + + 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; + + newHashParts[0] ^= nHigh; + newHashParts[1] ^= nLow; + newHashParts[2] ^= nHigh; + newHashParts[3] ^= nLow; + + /* swap more bytes if big endian */ + for (i = 0; i < 4; i ++) + newHashParts[i] = little_endian(newHashParts[i]); + + /* make a string of the parts */ + newHash = (unsigned char *)newHashParts; + + /* convert to hexadecimal */ + output = g_new(char, 33); + for (i = 0; i < 16; i ++) + sprintf(output + i * 2, "%02x", newHash[i]); + + return output; +} |