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