# HG changeset patch # User Jeffrey Connelly # Date 1178434110 0 # Node ID 58cd11fcd84fd20330823ecd745743449ca1c1fa # Parent 68f6611d6589c3e5affac57f3cfd74d52f370a0f Re-add RC4 code from Samba, whose use is enabled by not defining MSIM_USE_PURPLE_RC4. Otherwise, RC4 from Libpurple's cipher suite will be used. Needed to operate with Libpurple 2.0.0, which does not have an RC4 cipher. Closes #648 diff -r 68f6611d6589 -r 58cd11fcd84f libpurple/protocols/myspace/myspace.c --- a/libpurple/protocols/myspace/myspace.c Sat May 05 02:08:27 2007 +0000 +++ b/libpurple/protocols/myspace/myspace.c Sun May 06 06:48:30 2007 +0000 @@ -236,7 +236,7 @@ (token = tokens[i]); i++) { -#if MSIM_DEBUG_PARSE +#ifdef MSIM_DEBUG_PARSE purple_debug_info("msim", "tok=<%s>, i%2=%d\n", token, i % 2); #endif if (i % 2) @@ -249,7 +249,7 @@ /* Check if key already exists */ if (g_hash_table_lookup(table, key) == NULL) { -#if MSIM_DEBUG_PARSE +#ifdef MSIM_DEBUG_PARSE purple_debug_info("msim", "insert: |%s|=|%s|\n", key, value); #endif /* Insert - strdup 'key' because it will be g_strfreev'd (as 'tokens'), @@ -323,7 +323,7 @@ break; } -#if MSIM_DEBUG_PARSE +#ifdef MSIM_DEBUG_PARSE purple_debug_info("msim", "-- %s: %s\n", key, value); #endif @@ -343,7 +343,7 @@ -#if MSIM_DEBUG_MSG +#ifdef MSIM_DEBUG_MSG static void print_hash_item(gpointer key, gpointer value, gpointer user_data) { purple_debug_info("msim", "%s=%s\n", (char*)key, (char*)value); @@ -504,6 +504,114 @@ return 0; } +#ifndef MSIM_USE_PURPLE_RC4 +/* No RC4 in this version of libpurple, so bring our own. */ + +/* + Unix SMB/CIFS implementation. + + a partial implementation of RC4 designed for use in the + SMB authentication protocol + + Copyright (C) Andrew Tridgell 1998 + + $Id: crypt-rc4.c 12116 2004-09-27 23:29:22Z guy $ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + + Modified by Jeff Connelly for MySpaceIM Gaim plugin. +*/ + +#include +#include + +/* Perform RC4 on a block of data using specified key. "data" is a pointer + to the block to be processed. Output is written to same memory as input, + so caller may need to make a copy before calling this function, since + the input will be overwritten. + + Taken from Samba source code. Modified to allow us to maintain state + between calls to crypt_rc4. +*/ + +void crypt_rc4_init(rc4_state_struct *rc4_state, + const unsigned char *key, int key_len) +{ + int ind; + unsigned char j = 0; + unsigned char *s_box; + + memset(rc4_state, 0, sizeof(rc4_state_struct)); + s_box = rc4_state->s_box; + + for (ind = 0; ind < 256; ind++) + { + s_box[ind] = (unsigned char)ind; + } + + for( ind = 0; ind < 256; ind++) + { + unsigned char tc; + + j += (s_box[ind] + key[ind%key_len]); + + tc = s_box[ind]; + s_box[ind] = s_box[j]; + s_box[j] = tc; + } + +} + +void crypt_rc4(rc4_state_struct *rc4_state, unsigned char *data, int data_len) +{ + unsigned char *s_box; + unsigned char index_i; + unsigned char index_j; + int ind; + + /* retrieve current state from the state struct (so we can resume where + we left off) */ + index_i = rc4_state->index_i; + index_j = rc4_state->index_j; + s_box = rc4_state->s_box; + + for( ind = 0; ind < data_len; ind++) + { + unsigned char tc; + unsigned char t; + + index_i++; + index_j += s_box[index_i]; + + tc = s_box[index_i]; + s_box[index_i] = s_box[index_j]; + s_box[index_j] = tc; + + t = s_box[index_i] + s_box[index_j]; + data[ind] = data[ind] ^ s_box[t]; + } + + /* Store the updated state */ + rc4_state->index_i = index_i; + rc4_state->index_j = index_j; +} + +#endif /* !MSIM_USE_PURPLE_RC4 */ + + /** * Compute the base64'd login challenge response based on username, password, nonce, and IPs. * @@ -519,7 +627,12 @@ { PurpleCipherContext *key_context; PurpleCipher *sha1; +#ifdef MSIM_USE_PURPLE_RC4 PurpleCipherContext *rc4; +#else + rc4_state_struct rc4; +#endif + guchar hash_pw[HASH_SIZE]; guchar key[HASH_SIZE]; gchar* password_utf16le; @@ -529,7 +642,7 @@ size_t data_len, data_out_len; gsize conv_bytes_read, conv_bytes_written; GError* conv_error; -#if MSIM_DEBUG_LOGIN_CHALLENGE +#ifdef MSIM_DEBUG_LOGIN_CHALLENGE int i; #endif @@ -555,7 +668,7 @@ conv_bytes_written, sizeof(hash_pw), hash_pw, NULL); g_free(password_utf16le); -#if MSIM_DEBUG_LOGIN_CHALLENGE +#ifdef MSIM_DEBUG_LOGIN_CHALLENGE purple_debug_info("msim", "pwhash = "); for (i = 0; i < sizeof(hash_pw); i++) purple_debug_info("msim", "%.2x ", hash_pw[i]); @@ -569,7 +682,7 @@ purple_cipher_context_append(key_context, nonce + NONCE_SIZE, NONCE_SIZE); purple_cipher_context_digest(key_context, sizeof(key), key, NULL); -#if MSIM_DEBUG_LOGIN_CHALLENGE +#ifdef MSIM_DEBUG_LOGIN_CHALLENGE purple_debug_info("msim", "key = "); for (i = 0; i < sizeof(key); i++) { @@ -578,12 +691,14 @@ purple_debug_info("msim", "\n"); #endif +#ifdef MSIM_USE_PURPLE_RC4 rc4 = purple_cipher_context_new_by_name("rc4", NULL); /* Note: 'key' variable is 0x14 bytes (from SHA-1 hash), * but only first 0x10 used for the RC4 key. */ purple_cipher_context_set_option(rc4, "key_len", (gpointer)0x10); purple_cipher_context_set_key(rc4, key); +#endif /* TODO: obtain IPs of network interfaces. This is not immediately * important because you can still connect and perform basic @@ -599,18 +714,32 @@ memcpy(data, nonce, NONCE_SIZE); memcpy(data + NONCE_SIZE, email, strlen(email)); memcpy(data + NONCE_SIZE + strlen(email), - /* IP addresses of network interfaces */ + /* TODO: IP addresses of network interfaces */ "\x00\x00\x00\x00\x05\x7f\x00\x00\x01\x00\x00\x00\x00\x0a\x00\x00\x40\xc0\xa8\x58\x01\xc0\xa8\x3c\x01", 25); +#ifdef MSIM_USE_PURPLE_RC4 data_out = g_new0(guchar, data_len); + purple_cipher_context_encrypt(rc4, (const guchar*)data, data_len, data_out, &data_out_len); + purple_cipher_context_destroy(rc4); +#else + /* Use our own RC4 code */ + purple_debug_info("msim", "Using non-purple RC4 cipher code in this version\n"); + crypt_rc4_init(&rc4, key, 0x10); + crypt_rc4(&rc4, data, data_len); + data_out_len = data_len; + data_out = data; +#endif + g_assert(data_out_len == data_len); - purple_cipher_context_destroy(rc4); response = purple_base64_encode(data_out, data_out_len); +#ifdef MSIM_USE_PURPLE_RC4 g_free(data_out); -#if MSIM_DEBUG_LOGIN_CHALLENGE +#endif + +#ifdef MSIM_DEBUG_LOGIN_CHALLENGE purple_debug_info("msim", "response=<%s>\n", response); #endif @@ -849,7 +978,7 @@ session = (MsimSession*)gc->proto_data; -#if MSIM_DEBUG_MSG +#ifdef MSIM_DEBUG_MSG purple_debug_info("msim", "-------- message -------------\n"); g_hash_table_foreach(table, print_hash_item, NULL); purple_debug_info("msim", "------------------------------\n"); @@ -1244,7 +1373,7 @@ session->rxoff += n; purple_debug_info("msim", "msim_input_cb: read=%d\n", n); -#if MSIM_DEBUG_RXBUF +#ifdef MSIM_DEBUG_RXBUF purple_debug_info("msim", "buf=<%s>\n", session->rxbuf); #endif @@ -1253,7 +1382,7 @@ { GHashTable *table; -#if MSIM_DEBUG_RXBUF +#ifdef MSIM_DEBUG_RXBUF purple_debug_info("msim", "in loop: buf=<%s>\n", session->rxbuf); #endif *end = 0; diff -r 68f6611d6589 -r 58cd11fcd84f libpurple/protocols/myspace/myspace.h --- a/libpurple/protocols/myspace/myspace.h Sat May 05 02:08:27 2007 +0000 +++ b/libpurple/protocols/myspace/myspace.h Sun May 06 06:48:30 2007 +0000 @@ -19,12 +19,24 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Debugging options (1 to enable, 0 disable) */ -#define MSIM_DEBUG_MSG 1 +/* Conditional compilation options */ + +/* Debugging options */ +#define MSIM_DEBUG_MSG /* Low-level and rarely needed */ -#define MSIM_DEBUG_PARSE 0 -#define MSIM_DEBUG_LOGIN_CHALLENGE 0 -#define MSIM_DEBUG_RXBUF 0 +/*#define MSIM_DEBUG_PARSE */ +/*#define MSIM_DEBUG_LOGIN_CHALLENGE */ +/*#define MSIM_DEBUG_RXBUF */ + +/* RC4 didn't make it into Libpurple 2.0.0's cipher suite, so we have + * to use our own RC4 code (from Samba) by not defining this. */ +/*#define MSIM_USE_PURPLE_RC4 */ + +/* TODO: when RC4 makes it into libpurple, use the PURPLE_VERSION_CHECK + * macro to conditionally compile. And then later, get rid of our own + * RC4 code and only support libpurple with RC4. */ + +/* Constants */ /* Statuses */ #define MSIM_STATUS_ONLINE "online" @@ -150,3 +162,40 @@ static void msim_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full); +#ifndef MSIM_USE_PURPLE_RC4 +/* + Unix SMB/CIFS implementation. + + a partial implementation of RC4 designed for use in the + SMB authentication protocol + + Copyright (C) Andrew Tridgell 1998 + + $Id: crypt-rc4.h 12116 2004-09-27 23:29:22Z guy $ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +typedef struct _rc4_state_struct { + unsigned char s_box[256]; + unsigned char index_i; + unsigned char index_j; +} rc4_state_struct; + +void crypt_rc4_init(rc4_state_struct *rc4_state, + const unsigned char *key, int key_len); + +void crypt_rc4(rc4_state_struct *rc4_state, unsigned char *data, int data_len); +#endif /* !MSIM_USE_PURPLE_RC4 */