# HG changeset patch
# User andrew.victor@mxit.com
# Date 1309122202 0
# Node ID 3951afa56940a87baf32bc909acdad30eb597963
# Parent d872652ae4e42db725481c130c2fc9f21827325d
Start implementing MXit secure messaging.
* Decoding of transport-layer encrypted MXit messages.
diff -r d872652ae4e4 -r 3951afa56940 libpurple/protocols/mxit/cipher.c
--- a/libpurple/protocols/mxit/cipher.c Mon Jun 20 21:36:22 2011 +0000
+++ b/libpurple/protocols/mxit/cipher.c Sun Jun 26 21:03:22 2011 +0000
@@ -34,6 +34,7 @@
/* password encryption */
#define INITIAL_KEY "6170383452343567"
#define SECRET_HEADER ""
+#define ENCRYPT_HEADER ""
/*------------------------------------------------------------------------
@@ -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: */
+ 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: */
+ 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 );
+}
diff -r d872652ae4e4 -r 3951afa56940 libpurple/protocols/mxit/cipher.h
--- a/libpurple/protocols/mxit/cipher.h Mon Jun 20 21:36:22 2011 +0000
+++ b/libpurple/protocols/mxit/cipher.h Sun Jun 26 21:03:22 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_ */
diff -r d872652ae4e4 -r 3951afa56940 libpurple/protocols/mxit/protocol.c
--- a/libpurple/protocols/mxit/protocol.c Mon Jun 20 21:36:22 2011 +0000
+++ b/libpurple/protocols/mxit/protocol.c Sun Jun 26 21:03:22 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 );
}
diff -r d872652ae4e4 -r 3951afa56940 libpurple/protocols/mxit/protocol.h
--- a/libpurple/protocols/mxit/protocol.h Mon Jun 20 21:36:22 2011 +0000
+++ b/libpurple/protocols/mxit/protocol.h Sun Jun 26 21:03:22 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 */