pidgin.mxit: 62c1402a: Start implementing MXit secure messaging...

andrew.victor at mxit.com andrew.victor at mxit.com
Sun Jun 26 17:05:21 EDT 2011


----------------------------------------------------------------------
Revision: 62c1402a9d54bdc07737fbefdfeb664eb5f01d81
Parent:   6c013884b5884934bee1199eb43165ef688974da
Author:   andrew.victor at mxit.com
Date:     06/26/11 17:03:22
Branch:   im.pidgin.pidgin.mxit
URL: http://d.pidgin.im/viewmtn/revision/info/62c1402a9d54bdc07737fbefdfeb664eb5f01d81

Changelog: 

Start implementing MXit secure messaging.
* Decoding of transport-layer encrypted MXit messages.


Changes against parent 6c013884b5884934bee1199eb43165ef688974da

  patched  libpurple/protocols/mxit/cipher.c
  patched  libpurple/protocols/mxit/cipher.h
  patched  libpurple/protocols/mxit/protocol.c
  patched  libpurple/protocols/mxit/protocol.h

-------------- next part --------------
============================================================
--- libpurple/protocols/mxit/cipher.c	8a25e2dc92f45444edd1d4e1696e5124ce97c878
+++ libpurple/protocols/mxit/cipher.c	26ebbd25aa2117f929fe681e0ba1e5d3f91443bc
@@ -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 @@ char* mxit_encrypt_password( struct MXit
 	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 );
+}
============================================================
--- libpurple/protocols/mxit/cipher.h	3f071c302b9096c0a4f63cfbd3a2b9515e39d9f2
+++ libpurple/protocols/mxit/cipher.h	b1ae8268ab6a722286140d59e75a9fe10c580d25
@@ -32,5 +32,7 @@ char* mxit_encrypt_password( struct MXit
 
 char* mxit_encrypt_password( struct MXitSession* session );
 
+char* mxit_decrypt_message( struct MXitSession* session, char* message );
 
+
 #endif		/* _MXIT_CIPHER_H_ */
============================================================
--- libpurple/protocols/mxit/protocol.c	148f05b7484e2298528c3d37abf76360e1c7115a
+++ libpurple/protocols/mxit/protocol.c	b1112f35ca6f4a265d734861571f196774f014f7
@@ -1516,6 +1516,7 @@ static void mxit_parse_cmd_message( stru
 {
 	struct RXMsgData*	mx			= NULL;
 	char*				message		= NULL;
+	char*				sender		= NULL;
 	int					msglen		= 0;
 	int					msgflags	= 0;
 	int					msgtype		= 0;
@@ -1529,10 +1530,11 @@ static void mxit_parse_cmd_message( stru
 	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 @@ static void mxit_parse_cmd_message( stru
 		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 @@ static void mxit_parse_cmd_message( stru
 		 * so the image received callback function will eventually display
 		 * the message. */
 	}
+
+	/* cleanup */
+	if ( msgflags & CP_MSG_TL_ENCRYPTED )
+		g_free( message );
 }
 
 
============================================================
--- libpurple/protocols/mxit/protocol.h	cd86cea741fc786d0fd9969fb8a49b69ac44a52d
+++ libpurple/protocols/mxit/protocol.h	b321444fe2576c1fde7c4549811fa44727b9b004
@@ -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 */
 


More information about the Commits mailing list