changeset 31879:5cb66143ae2a

propagate from branch 'im.pidgin.pidgin' (head 8f0dbb75e0842b6df34c773ceb3a62e07819c532) to branch 'im.pidgin.pidgin.mxit' (head 58ce8d40af953c67a284a42e026ccdbfd25ffaa8)
author andrew.victor@mxit.com
date Fri, 12 Aug 2011 21:41:34 +0000
parents 88a1d883e65f (diff) 04ff99311108 (current diff)
children 66fa012633e9
files libpurple/protocols/mxit/cipher.c
diffstat 6 files changed, 134 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/protocols/mxit/cipher.c	Thu Aug 11 18:31:02 2011 +0000
+++ b/libpurple/protocols/mxit/cipher.c	Fri Aug 12 21:41:34 2011 +0000
@@ -34,6 +34,7 @@
 /* password encryption */
 #define		INITIAL_KEY		"6170383452343567"
 #define		SECRET_HEADER	"<mxit/>"
+#define		ENCRYPT_HEADER	"<mxitencrypted ver=\"5.2\"/>"
 
 
 /*------------------------------------------------------------------------
@@ -106,3 +107,62 @@
 	return base64;
 }
 
+
+/*------------------------------------------------------------------------
+ * Decrypt a transport-layer encryptede message.
+ *
+ *  @param session	The MXit session object
+ *	@param message	The encrypted message data.
+ *  @return			The decrypted message.  Must be g_free'd when no longer needed.
+ */
+char* mxit_decrypt_message( struct MXitSession* session, char* message )
+{
+	gsize		raw_len;
+	guchar*		raw_message;
+	char		key[64];
+	int			pwdlen		= strlen( session->acc->password );
+	char		exkey[512];
+	int			i;
+	GString*	decoded		= NULL;
+
+	/* remove optional header: <mxitencrypted ver="5.2"/> */
+	if ( strncmp( message, ENCRYPT_HEADER, strlen( ENCRYPT_HEADER ) ) == 0 )
+		message += strlen( ENCRYPT_HEADER );
+
+	/* base64 decode the message */
+	raw_message = purple_base64_decode( message, &raw_len );
+
+	/* build the key - Client key, appended with last 8 characters of the PIN. (no padding) */
+	memset( key, 0x00, sizeof( key ) );
+	memcpy( key, session->clientkey, strlen( session->clientkey ) );
+	if ( pwdlen <= 8 )
+		strcat( key, session->acc->password );
+	else
+		strncat( key, session->acc->password + ( pwdlen - 8 ), 8 );
+	ExpandKey( (unsigned char*) key, (unsigned char*) exkey );
+
+	/* decode each block */
+	decoded = g_string_sized_new( raw_len );
+	for ( i = 0; i < raw_len; i += 16 ) {
+		char	block[16];
+
+		Decrypt( (unsigned char*) raw_message + i, (unsigned char*) exkey, (unsigned char*) block );
+		g_string_append_len( decoded, block, 16 );
+	}
+
+	g_free( raw_message );
+
+	purple_debug_info( MXIT_PLUGIN_ID, "decrypted: '%s'\n", decoded->str );
+
+	/* check that the decrypted message starts with header: <mxit/> */
+	if ( strncmp( decoded->str, SECRET_HEADER, strlen( SECRET_HEADER ) != 0 ) ) {
+		g_string_free( decoded, TRUE );
+		return NULL;			/* message could not be decoded */
+	}
+	g_string_erase( decoded, 0, strlen( SECRET_HEADER ) );		/* remove header */
+
+	/* remove ISO10126 padding */
+// TODO
+
+	return g_string_free( decoded, FALSE );
+}
--- a/libpurple/protocols/mxit/cipher.h	Thu Aug 11 18:31:02 2011 +0000
+++ b/libpurple/protocols/mxit/cipher.h	Fri Aug 12 21:41:34 2011 +0000
@@ -32,5 +32,7 @@
 
 char* mxit_encrypt_password( struct MXitSession* session );
 
+char* mxit_decrypt_message( struct MXitSession* session, char* message );
+
 
 #endif		/* _MXIT_CIPHER_H_ */
--- a/libpurple/protocols/mxit/markup.c	Thu Aug 11 18:31:02 2011 +0000
+++ b/libpurple/protocols/mxit/markup.c	Fri Aug 12 21:41:34 2011 +0000
@@ -735,6 +735,7 @@
 	gboolean	tag_bold	= FALSE;
 	gboolean	tag_under	= FALSE;
 	gboolean	tag_italic	= FALSE;
+	int			font_size	= 0;
 
 #ifdef MXIT_DEBUG_MARKUP
 	purple_debug_info( MXIT_PLUGIN_ID, "Markup RX (original): '%s'\n", message );
@@ -862,59 +863,54 @@
 					}
 					break;
 			case '.' :
-					if ( !( msgflags & CP_MSG_EMOTICON ) ) {
-						g_string_append_c( mx->msg, message[i] );
-						break;
-					}
-					else if ( i + 1 >= len ) {
+					if ( i + 1 >= len ) {
 						/* message too short */
 						g_string_append_c( mx->msg, '.' );
 						break;
 					}
 
-					switch ( message[i+1] ) {
-						case '+' :
-								/* increment text size */
-								g_string_append( mx->msg, "<font size=\"+1\">" );
-								i++;
-								break;
-						case '-' :
-								/* decrement text size */
-								g_string_append( mx->msg, "<font size=\"-1\">" );
-								i++;
-								break;
-						case '{' :
-								/* custom emoticon */
-								if ( i + 2 >= len ) {
-									/* message too short */
-									g_string_append_c( mx->msg, '.' );
-									break;
-								}
+					if ( ( msgflags & CP_MSG_EMOTICON ) && ( message[i+1] == '{' ) ) {
+						/* custom emoticon */
+						if ( i + 2 >= len ) {
+							/* message too short */
+							g_string_append_c( mx->msg, '.' );
+							break;
+						}
+
+						parse_emoticon_str( &message[i+2], tmpstr1 );
+						if ( tmpstr1[0] != '\0' ) {
+							mx->got_img = TRUE;
+
+							if ( g_hash_table_lookup( mx->session->iimages, tmpstr1 ) ) {
+								/* emoticon found in the cache, so we do not have to request it from the WAPsite */
+							}
+							else {
+								/* request emoticon from the WAPsite */
+								mx->img_count++;
+								emoticon_request( mx, tmpstr1 );
+							}
 
-								parse_emoticon_str( &message[i+2], tmpstr1 );
-								if ( tmpstr1[0] != '\0' ) {
-									mx->got_img = TRUE;
+							g_string_append_printf( mx->msg, MXIT_II_TAG"%s>", tmpstr1 );
+							i += strlen( tmpstr1 ) + 2;
+						}
+						else
+							g_string_append_c( mx->msg, '.' );
+					}
+					else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '+' ) ) {
+						/* increment text size */
+						font_size++;
+						g_string_append_printf( mx->msg, "<font size=\"%+i\">", font_size );
+						i++;
+					}
+					else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '-' ) ) {
+						/* decrement text size */
+						font_size--;
+						g_string_append_printf( mx->msg, "<font size=\"%+i\">", font_size );
+						i++;
+					}
+					else
+						g_string_append_c( mx->msg, '.' );
 
-									if ( g_hash_table_lookup( mx->session->iimages, tmpstr1 ) ) {
-										/* emoticon found in the cache, so we do not have to request it from the WAPsite */
-									}
-									else {
-										/* request emoticon from the WAPsite */
-										mx->img_count++;
-										emoticon_request( mx, tmpstr1 );
-									}
-
-									g_string_append_printf( mx->msg, MXIT_II_TAG"%s>", tmpstr1 );
-									i += strlen( tmpstr1 ) + 2;
-								}
-								else
-									g_string_append_c( mx->msg, '.' );
-
-								break;
-						default :
-								g_string_append_c( mx->msg, '.' );
-								break;
-					}
 					break;
 			case '\\' :
 					if ( i + 1 >= len ) {
--- a/libpurple/protocols/mxit/protocol.c	Thu Aug 11 18:31:02 2011 +0000
+++ b/libpurple/protocols/mxit/protocol.c	Fri Aug 12 21:41:34 2011 +0000
@@ -1516,6 +1516,7 @@
 {
 	struct RXMsgData*	mx			= NULL;
 	char*				message		= NULL;
+	char*				sender		= NULL;
 	int					msglen		= 0;
 	int					msgflags	= 0;
 	int					msgtype		= 0;
@@ -1529,10 +1530,11 @@
 	msglen = strlen( message );
 
 	/* strip off dummy domain */
-	mxit_strip_domain( records[0]->fields[0]->data );
+	sender = records[0]->fields[0]->data;
+	mxit_strip_domain( sender );
 
 #ifdef	DEBUG_PROTOCOL
-	purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", records[0]->fields[0]->data );
+	purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", sender );
 #endif
 
 	/* decode message flags (if any) */
@@ -1540,33 +1542,42 @@
 		msgflags = atoi( records[0]->fields[4]->data );
 	msgtype = atoi( records[0]->fields[2]->data );
 
-	if ( msgflags & CP_MSG_ENCRYPTED ) {
-		/* this is an encrypted message. we do not currently support those so ignore it */
+	if ( msgflags & CP_MSG_PWD_ENCRYPTED ) {
+		/* this is a password encrypted message. we do not currently support those so ignore it */
 		PurpleBuddy*	buddy;
 		const char*		name;
 		char			msg[128];
 
-		buddy = purple_find_buddy( session->acc, records[0]->fields[0]->data );
+		buddy = purple_find_buddy( session->acc, sender );
 		if ( buddy )
 			name = purple_buddy_get_alias( buddy );
 		else
-			name = records[0]->fields[0]->data;
+			name = sender;
 		g_snprintf( msg, sizeof( msg ), _( "%s sent you an encrypted message, but it is not supported on this client." ), name );
 		mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), msg );
 		return;
 	}
+	else if ( msgflags & CP_MSG_TL_ENCRYPTED ) {
+		/* this is a transport-layer encrypted message. */
+		message = mxit_decrypt_message( session, message );
+		if ( !message ) {
+			/* could not be decrypted */
+			serv_got_im( session->con, sender, _( "An encrypted message was received which could not be decrypted." ), PURPLE_MESSAGE_ERROR, time( NULL ) );
+			return;
+		}
+	}
 
 	if ( msgflags & CP_MSG_NOTIFY_DELIVERY ) {
 		/* delivery notification is requested */
 		if ( records[0]->fcount >= 4 )
-			mxit_send_msgevent( session, records[0]->fields[0]->data, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED );
+			mxit_send_msgevent( session, sender, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED );
 	}
 
 	/* create and initialise new markup struct */
 	mx = g_new0( struct RXMsgData, 1 );
 	mx->msg = g_string_sized_new( msglen );
 	mx->session = session;
-	mx->from = g_strdup( records[0]->fields[0]->data );
+	mx->from = g_strdup( sender );
 	mx->timestamp = atoi( records[0]->fields[1]->data );
 	mx->got_img = FALSE;
 	mx->chatid = -1;
@@ -1597,6 +1608,10 @@
 		 * so the image received callback function will eventually display
 		 * the message. */
 	}
+
+	/* cleanup */
+	if ( msgflags & CP_MSG_TL_ENCRYPTED )
+		g_free( message );
 }
 
 
--- a/libpurple/protocols/mxit/protocol.h	Thu Aug 11 18:31:02 2011 +0000
+++ b/libpurple/protocols/mxit/protocol.h	Fri Aug 12 21:41:34 2011 +0000
@@ -155,7 +155,10 @@
 /* message flags */
 #define		CP_MSG_NOTIFY_DELIVERY	0x0002					/* request delivery notification */
 #define		CP_MSG_NOTIFY_READ		0x0004					/* request read notification */
-#define		CP_MSG_ENCRYPTED		0x0010					/* message is encrypted */
+#define		CP_MSG_PWD_ENCRYPTED	0x0010					/* message is password encrypted */
+#define		CP_MSG_TL_ENCRYPTED		0x0020					/* message is transport encrypted */
+#define		CP_MSG_RPLY_PWD_ENCRYPT	0x0040					/* reply should be password encrypted */
+#define		CP_MSG_RPLY_TL_ENCRYPT	0x0080					/* reply should be transport encrypted */
 #define		CP_MSG_MARKUP			0x0200					/* message may contain markup */
 #define		CP_MSG_EMOTICON			0x0400					/* message may contain custom emoticons */
 
--- a/libpurple/protocols/mxit/roster.h	Thu Aug 11 18:31:02 2011 +0000
+++ b/libpurple/protocols/mxit/roster.h	Fri Aug 12 21:41:34 2011 +0000
@@ -96,7 +96,7 @@
 /* client protocol constants */
 #define		MXIT_CP_MAX_JID_LEN			64
 #define		MXIT_CP_MAX_GROUP_LEN		32
-#define		MXIT_CP_MAX_ALIAS_LEN		48
+#define		MXIT_CP_MAX_ALIAS_LEN		100
 
 #define		MXIT_DEFAULT_GROUP			"MXit"
 
@@ -106,8 +106,8 @@
  */
 struct contact {
 	char		username[MXIT_CP_MAX_JID_LEN+1];	/* unique contact name (with domain) */
-	char		alias[MXIT_CP_MAX_GROUP_LEN+1];		/* contact alias (what will be seen) */
-	char		groupname[MXIT_CP_MAX_ALIAS_LEN+1];	/* contact group name */
+	char		alias[MXIT_CP_MAX_ALIAS_LEN+1];		/* contact alias (what will be seen) */
+	char		groupname[MXIT_CP_MAX_GROUP_LEN+1];	/* contact group name */
 
 	short		type;								/* contact type */
 	short		mood;								/* contact current mood */