diff options
Diffstat (limited to 'protocols/msn/msn_util.c')
-rw-r--r-- | protocols/msn/msn_util.c | 137 |
1 files changed, 98 insertions, 39 deletions
diff --git a/protocols/msn/msn_util.c b/protocols/msn/msn_util.c index 23447403..bd1bea42 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 ) @@ -32,6 +33,12 @@ int msn_write( struct im_connection *ic, char *s, int len ) struct msn_data *md = ic->proto_data; int st; + if( getenv( "BITLBEE_DEBUG" ) ) + { + write( 2, "->NS:", 5 ); + write( 2, s, len ); + } + st = write( md->fd, s, len ); if( st != len ) { @@ -53,7 +60,7 @@ int msn_logged_in( struct im_connection *ic ) int msn_buddy_list_add( struct im_connection *ic, const char *list, const char *who, const char *realname_, const char *group ) { struct msn_data *md = ic->proto_data; - char buf[1024], *realname, groupid[8]; + char buf[1024], realname[strlen(realname_)*3+1], groupid[8]; *groupid = '\0'; if( group ) @@ -86,9 +93,10 @@ int msn_buddy_list_add( struct im_connection *ic, const char *list, const char * if( l == NULL ) { - char *groupname = msn_http_encode( group ); + char groupname[strlen(group)+1]; + strcpy( groupname, group ); + http_encode( groupname ); g_snprintf( buf, sizeof( buf ), "ADG %d %s %d\r\n", ++md->trId, groupname, 0 ); - g_free( groupname ); return msn_write( ic, buf, strlen( buf ) ); } else @@ -101,9 +109,9 @@ int msn_buddy_list_add( struct im_connection *ic, const char *list, const char * } } - realname = msn_http_encode( realname_ ); + strcpy( realname, realname_ ); + http_encode( realname ); g_snprintf( buf, sizeof( buf ), "ADD %d %s %s %s%s\r\n", ++md->trId, list, who, realname, groupid ); - g_free( realname ); return msn_write( ic, buf, strlen( buf ) ); } @@ -279,6 +287,12 @@ int msn_handler( struct msn_handler_data *h ) if( st <= 0 ) return( -1 ); + if( getenv( "BITLBEE_DEBUG" ) ) + { + write( 2, "->C:", 4 ); + write( 2, h->rxq + h->rxlen - st, st ); + } + while( st ) { int i; @@ -366,32 +380,6 @@ int msn_handler( struct msn_handler_data *h ) return( 1 ); } -/* The difference between this function and the normal http_encode() function - is that this one escapes every 7-bit ASCII character because this is said - to avoid some lame server-side checks when setting a real-name. Also, - non-ASCII characters are not escaped because MSN servers don't seem to - appreciate that! */ -char *msn_http_encode( const char *input ) -{ - char *ret, *s; - int i; - - ret = s = g_new0( char, strlen( input ) * 3 + 1 ); - for( i = 0; input[i]; i ++ ) - if( input[i] & 128 ) - { - *s = input[i]; - s ++; - } - else - { - g_snprintf( s, 4, "%%%02X", input[i] ); - s += 3; - } - - return ret; -} - void msn_msgq_purge( struct im_connection *ic, GSList **list ) { struct msn_message *m; @@ -432,14 +420,85 @@ void msn_msgq_purge( struct im_connection *ic, GSList **list ) g_string_free( ret, TRUE ); } -gboolean msn_set_display_name( struct im_connection *ic, const char *rawname ) +/* Copied and heavily modified from http://tmsnc.sourceforge.net/chl.c */ +char *msn_p11_challenge( char *challenge ) { - char *fn = msn_http_encode( rawname ); - struct msn_data *md = ic->proto_data; - char buf[1024]; + 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] = GUINT32_TO_LE(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] = GUINT32_TO_LE(chlStringParts[i]); + chlStringParts[i+1] = GUINT32_TO_LE(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; - g_snprintf( buf, sizeof( buf ), "REA %d %s %s\r\n", ++md->trId, ic->acc->user, fn ); - g_free( fn ); + newHashParts[0] ^= nHigh; + newHashParts[1] ^= nLow; + newHashParts[2] ^= nHigh; + newHashParts[3] ^= nLow; - return msn_write( ic, buf, strlen( buf ) ) != 0; + /* swap more bytes if big endian */ + for (i = 0; i < 4; i ++) + newHashParts[i] = GUINT32_TO_LE(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; +} + +gint msn_domaintree_cmp( gconstpointer a_, gconstpointer b_ ) +{ + const char *a = a_, *b = b_; + gint ret; + + if( !( a = strchr( a, '@' ) ) || !( b = strchr( b, '@' ) ) || + ( ret = strcmp( a, b ) ) == 0 ) + ret = strcmp( a_, b_ ); + + return ret; } |