Mercurial > pidgin
changeset 24138:dc112387190f
2008.09.29 - ccpaging <ccpaging(at)gmail.com>
* 'Check Password' function for protocol 2007/2008
author | SHiNE CsyFeK <csyfek@gmail.com> |
---|---|
date | Wed, 22 Oct 2008 14:41:13 +0000 |
parents | 87e61a85f5dd |
children | 832178d951ca |
files | libpurple/protocols/qq/ChangeLog libpurple/protocols/qq/buddy_opt.c libpurple/protocols/qq/group_join.c libpurple/protocols/qq/im.c libpurple/protocols/qq/qq.h libpurple/protocols/qq/qq_base.c libpurple/protocols/qq/qq_network.c libpurple/protocols/qq/qq_process.c |
diffstat | 8 files changed, 145 insertions(+), 118 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/protocols/qq/ChangeLog Wed Oct 22 14:40:04 2008 +0000 +++ b/libpurple/protocols/qq/ChangeLog Wed Oct 22 14:41:13 2008 +0000 @@ -1,3 +1,6 @@ +2008.09.29 - ccpaging <ccpaging(at)gmail.com> + * 'Check Password' function for protocol 2007/2008 + 2008.09.28 - ccpaging <ccpaging(at)gmail.com> * The source is only for debug, not for user: 1. Implement new QQ protocol 2007/2008, include login and change status
--- a/libpurple/protocols/qq/buddy_opt.c Wed Oct 22 14:40:04 2008 +0000 +++ b/libpurple/protocols/qq/buddy_opt.c Wed Oct 22 14:41:13 2008 +0000 @@ -512,7 +512,7 @@ g_return_val_if_fail(gc->account != NULL && uid != 0, NULL); qd = (qq_data *) gc->proto_data; - if (is_known || uid == qd->uid) { + if (is_known) { group_name = g_strdup_printf(PURPLE_GROUP_QQ_FORMAT, purple_account_get_username(gc->account)); } else { @@ -529,7 +529,7 @@ purple_blist_remove_buddy(buddy); buddy = purple_buddy_new(gc->account, buddy_name, NULL); - if ( !is_known && uid != qd->uid) { + if ( !is_known) { if (purple_privacy_check(gc->account, buddy_name)) { purple_privacy_deny(gc->account, buddy_name, TRUE, FALSE); } else {
--- a/libpurple/protocols/qq/group_join.c Wed Oct 22 14:40:04 2008 +0000 +++ b/libpurple/protocols/qq/group_join.c Wed Oct 22 14:41:13 2008 +0000 @@ -39,6 +39,7 @@ #include "group_opt.h" #include "group_conv.h" #include "group_search.h" +#include "group_im.h" #include "qq_define.h" #include "packet_parse.h" #include "qq_network.h" @@ -226,6 +227,9 @@ gint bytes; guint32 id; qq_data *qd; + qq_group *group; + gchar *msg; + time_t now = time(NULL); g_return_if_fail(data != NULL && len > 0); qd = (qq_data *) gc->proto_data; @@ -239,7 +243,14 @@ bytes += qq_get32(&id, data + bytes); g_return_if_fail(id > 0); - qq_got_attention(gc, _("Successed join to Qun")); + group = qq_room_search_id(gc, id); + if (group != NULL) { + msg = g_strdup_printf(_("Successed join to Qun %s (%d)"), group->title_utf8, group->ext_id); + qq_room_got_chat_in(gc, group, 0, msg, now); + g_free(msg); + } else { + qq_got_attention(gc, _("Successed join to Qun")); + } } /* process group cmd reply "join group" */
--- a/libpurple/protocols/qq/im.c Wed Oct 22 14:40:04 2008 +0000 +++ b/libpurple/protocols/qq/im.c Wed Oct 22 14:41:13 2008 +0000 @@ -298,24 +298,21 @@ { qq_data *qd; gchar *from; - PurpleBuddy *b; - qq_buddy *qq_b; + PurpleBuddy *buddy; time_t now = time(NULL); qd = (qq_data *) gc->proto_data; - from = uid_to_purple_name(qd->uid); g_return_if_fail(qd->uid > 0); - b = purple_find_buddy(gc->account, from); - if (b == NULL) { - qq_create_buddy(gc, qd->uid, FALSE, TRUE); - b = purple_find_buddy(gc->account, from); + from = uid_to_purple_name(qd->uid); + buddy = purple_find_buddy(gc->account, from); + if (buddy == NULL) { + qq_create_buddy(gc, qd->uid, TRUE, TRUE); } - qq_b = (b == NULL) ? NULL : (qq_buddy *) b->proto_data; - g_return_if_fail(qq_b != NULL); serv_got_im(gc, from, msg, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NOTIFY, now); + g_free(from); } /* process received normal text IM */
--- a/libpurple/protocols/qq/qq.h Wed Oct 22 14:40:04 2008 +0000 +++ b/libpurple/protocols/qq/qq.h Wed Oct 22 14:41:13 2008 +0000 @@ -60,8 +60,8 @@ guint8 *token_ex; /* get from server */ guint16 token_ex_len; - guint8 pwd_2nd_md5[QQ_KEY_LENGTH]; /* password in md5 (or md5' md5) */ - guint8 pwd_4th_md5[QQ_KEY_LENGTH]; + guint8 pwd_md5[QQ_KEY_LENGTH]; /* password in md5 (or md5' md5) */ + guint8 pwd_twice_md5[QQ_KEY_LENGTH]; guint8 *login_token; guint16 login_token_len; @@ -73,7 +73,7 @@ guint8 b1; guint32 w1; guint32 w2; - guint32 ip; + struct in_addr ip; }; struct _qq_add_request {
--- a/libpurple/protocols/qq/qq_base.c Wed Oct 22 14:40:04 2008 +0000 +++ b/libpurple/protocols/qq/qq_base.c Wed Oct 22 14:41:13 2008 +0000 @@ -34,16 +34,13 @@ #include "qq_crypt.h" #include "group.h" #include "qq_define.h" +#include "qq_network.h" #include "qq_base.h" #include "packet_parse.h" #include "qq.h" #include "qq_network.h" #include "utils.h" -#define QQ_LOGIN_DATA_LENGTH 416 -#define QQ_LOGIN_REPLY_OK_PACKET_LEN 139 -#define QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN 11 - /* generate a md5 key using uid and session_key */ static void get_session_md5(guint8 *session_md5, guint32 uid, guint8 *session_key) { @@ -71,7 +68,13 @@ qd = (qq_data *) gc->proto_data; qq_show_packet("Login reply", data, len); - /* FIXME, check QQ_LOGIN_REPLY_OK_PACKET_LEN here */ + if (len < 139) { + purple_connection_error_reason(gc, + PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, + _("Can not decrypt get server reply")); + return QQ_LOGIN_REPLY_ERR; + } + bytes = 0; bytes += qq_get8(&ret, data + bytes); bytes += qq_getdata(qd->session_key, sizeof(qd->session_key), data + bytes); @@ -134,11 +137,9 @@ tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); /* unknow 9 bytes, 0x(00 0a 00 0a 01 00 00 0e 10) */ - if (bytes != QQ_LOGIN_REPLY_OK_PACKET_LEN) { /* fail parsing login info */ - purple_debug_warning("QQ", - "Fail parsing login info, expect %d bytes, read %d bytes\n", - QQ_LOGIN_REPLY_OK_PACKET_LEN, bytes); - } /* but we still go on as login OK */ + if (len > 139) { + purple_debug_warning("QQ", "Login reply more than expected %d bytes, read %d bytes\n", 139, bytes); + } return QQ_LOGIN_REPLY_OK; } @@ -155,6 +156,13 @@ } packet; + if (len < 11) { + purple_connection_error_reason(gc, + PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, + _("Can not decrypt get server reply")); + return QQ_LOGIN_REPLY_ERR; + } + qd = (qq_data *) gc->proto_data; bytes = 0; /* 000-000: reply code */ @@ -166,11 +174,8 @@ /* 009-010: redirected new server port */ bytes += qq_get16(&packet.new_server_port, data + bytes); - if (bytes != QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN) { - purple_debug_error("QQ", - "Fail parsing login redirect packet, expect %d bytes, read %d bytes\n", - QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN, bytes); - return QQ_LOGIN_REPLY_ERR; + if (len > 11) { + purple_debug_error("QQ", "Login redirect more than expected %d bytes, read %d bytes\n", 11, bytes); } /* redirect to new server, do not disconnect or connect here @@ -239,15 +244,15 @@ g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); - raw_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH); - memset(raw_data, 0, QQ_LOGIN_DATA_LENGTH); + raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16); + memset(raw_data, 0, MAX_PACKET_SIZE - 16); - encrypted = g_newa(guint8, QQ_LOGIN_DATA_LENGTH + 16); /* 16 bytes more */ + encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ bytes = 0; /* now generate the encrypted data * 000-015 use password_twice_md5 as key to encrypt empty string */ - encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_2nd_md5); + encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5); g_return_if_fail(encrypted_len == 16); bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); @@ -270,8 +275,10 @@ /* 100 bytes unknown */ bytes += qq_putdata(raw_data + bytes, login_100_bytes, 100); /* all zero left */ + memset(raw_data + bytes, 0, 416 - bytes); + bytes = 416; - encrypted_len = qq_encrypt(encrypted, raw_data, QQ_LOGIN_DATA_LENGTH, qd->ld.random_key); + encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); buf = g_newa(guint8, MAX_PACKET_SIZE); memset(buf, 0, MAX_PACKET_SIZE); @@ -350,7 +357,7 @@ qd = (qq_data *) gc->proto_data; for (i = 0; i < 4; i++) - qq_send_cmd(gc, QQ_CMD_LOGOUT, qd->ld.pwd_2nd_md5, QQ_KEY_LENGTH); + qq_send_cmd(gc, QQ_CMD_LOGOUT, qd->ld.pwd_twice_md5, QQ_KEY_LENGTH); qd->is_login = FALSE; /* update login status AFTER sending logout packets */ } @@ -502,15 +509,19 @@ g_return_if_fail(gc != NULL && gc->proto_data != NULL); qd = (qq_data *) gc->proto_data; - raw_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH); - memset(raw_data, 0, QQ_LOGIN_DATA_LENGTH); + raw_data = g_newa(guint8, sizeof(qd->redirect_data)); + memset(raw_data, 0, sizeof(qd->redirect_data)); - encrypted = g_newa(guint8, QQ_LOGIN_DATA_LENGTH + 16); /* 16 bytes more */ + encrypted = g_newa(guint8, sizeof(qd->redirect_data) + 16); /* 16 bytes more */ bytes = 0; - bytes += qq_putdata(raw_data + bytes, (guint8 *)&qd->redirect_data, sizeof(qd->redirect_data)); + bytes += qq_put16(raw_data + bytes, qd->redirect_data.ret); + bytes += qq_put8(raw_data + bytes, qd->redirect_data.b1); + bytes += qq_put32(raw_data + bytes, qd->redirect_data.w1); + bytes += qq_put32(raw_data + bytes, qd->redirect_data.w2); + bytes += qq_putIP(raw_data + bytes, &(qd->redirect_data.ip)); - encrypted_len = qq_encrypt(encrypted, raw_data, QQ_LOGIN_DATA_LENGTH, qd->ld.random_key); + encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); buf = g_newa(guint8, MAX_PACKET_SIZE); memset(buf, 0, MAX_PACKET_SIZE); @@ -519,34 +530,44 @@ bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); + qq_send_cmd_encrypted(gc, QQ_CMD_GET_SERVER, qd->send_seq, buf, bytes, TRUE); } guint16 qq_process_get_server(PurpleConnection *gc, guint8 *data, gint data_len) { qq_data *qd; - qq_redirect_data *redirect; + gint bytes; g_return_val_if_fail (gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR); qd = (qq_data *) gc->proto_data; g_return_val_if_fail (data != NULL, QQ_LOGIN_REPLY_ERR); - if (data_len < sizeof(qq_redirect_data)) { - purple_connection_error_reason(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Can not decrypt get server reply")); - return QQ_LOGIN_REPLY_ERR; - } - - redirect = (qq_redirect_data *)data; - if (redirect->ret == 0) { + + /* qq_show_packet("Get Server", data, data_len); */ + bytes = 0; + bytes += qq_get16(&qd->redirect_data.ret, data + bytes); + if (qd->redirect_data.ret == 0) { memset(&qd->redirect_data, 0, sizeof(qd->redirect_data)); qd->redirect_ip.s_addr = 0; return QQ_LOGIN_REPLY_OK; } - g_memmove(&qd->redirect_data, redirect, sizeof(qd->redirect_data)); - g_memmove(&qd->redirect_ip, &redirect->ip, sizeof(qd->redirect_ip)); + if (data_len < 15) { + purple_connection_error_reason(gc, + PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, + _("Can not decrypt get server reply")); + return QQ_LOGIN_REPLY_ERR; + } + + bytes += qq_get8(&qd->redirect_data.b1, data + bytes); + bytes += qq_get32(&qd->redirect_data.w1, data + bytes); + bytes += qq_get32(&qd->redirect_data.w2, data + bytes); + bytes += qq_getIP(&qd->redirect_data.ip, data + bytes); + purple_debug_info("QQ", "Get server %d-%d-%d%d, %s\n", + qd->redirect_data.ret, qd->redirect_data.b1, qd->redirect_data.w1, qd->redirect_data.w2, + inet_ntoa(qd->redirect_data.ip)); + + g_memmove(&qd->redirect_ip, &qd->redirect_data.ip, sizeof(qd->redirect_ip)); return QQ_LOGIN_REPLY_REDIRECT; } @@ -577,7 +598,7 @@ bytes += qq_put8(raw_data + bytes, 0); /* fragment index */ bytes += qq_put16(raw_data + bytes, 0); /* captcha token */ - encrypted_len = qq_encrypt(encrypted, raw_data, QQ_LOGIN_DATA_LENGTH, qd->ld.random_key); + encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); buf = g_newa(guint8, MAX_PACKET_SIZE); memset(buf, 0, MAX_PACKET_SIZE); @@ -617,7 +638,7 @@ bytes += qq_put16(raw_data + bytes, qd->captcha.token_len); /* captcha token */ bytes += qq_putdata(raw_data + bytes, qd->captcha.token, qd->captcha.token_len); - encrypted_len = qq_encrypt(encrypted, raw_data, QQ_LOGIN_DATA_LENGTH, qd->ld.random_key); + encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); buf = g_newa(guint8, MAX_PACKET_SIZE); memset(buf, 0, MAX_PACKET_SIZE); @@ -662,7 +683,7 @@ bytes += qq_put16(raw_data + bytes, qd->captcha.token_len); /* captcha token */ bytes += qq_putdata(raw_data + bytes, qd->captcha.token, qd->captcha.token_len); - encrypted_len = qq_encrypt(encrypted, raw_data, QQ_LOGIN_DATA_LENGTH, qd->ld.random_key); + encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); buf = g_newa(guint8, MAX_PACKET_SIZE); memset(buf, 0, MAX_PACKET_SIZE); @@ -783,8 +804,8 @@ ret = data[0]; bytes = 0; - bytes += qq_get8(&sub_cmd, data + bytes); - bytes += 2; + bytes += qq_get8(&sub_cmd, data + bytes); /* 03: ok; 04: need verifying */ + bytes += 2; /* 0x(00 05) */ bytes += qq_get8(&reply, data + bytes); bytes += qq_get16(&(qd->ld.token_ex_len), data + bytes); @@ -794,7 +815,7 @@ if(reply != 1) { - purple_debug_info("QQ", "Captcha verified\n"); + purple_debug_info("QQ", "Captcha verified, result %d\n", reply); return QQ_LOGIN_REPLY_OK; } @@ -863,8 +884,9 @@ gint bytes; guint8 *encrypted; gint encrypted_len; + gint count; static guint8 header[] = { - 0x00, 0x5F, 0x00, 0x00, 0x08, 0x04, 0x01, 0x0E + 0x00, 0x5F, 0x00, 0x00, 0x08, 0x04, 0x01, 0xE0 }; g_return_if_fail(gc != NULL && gc->proto_data != NULL); @@ -879,39 +901,35 @@ /* Encrypted password and put in encrypted */ bytes = 0; - bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_2nd_md5, sizeof(qd->ld.pwd_2nd_md5)); - bytes += qq_put16(raw_data + bytes, 0); - bytes += qq_put16(raw_data + bytes, 0); + bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); + bytes += qq_put16(raw_data + bytes, rand() & 0); + bytes += qq_put16(raw_data + bytes, rand() & 0xffff); - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_4th_md5); - + encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); /* create packet */ bytes = 0; bytes += qq_putdata(raw_data + bytes, header, sizeof(header)); /* token get from qq_process_token_ex */ - bytes += qq_put16(raw_data + bytes, qd->ld.token_ex_len); + bytes += qq_put8(raw_data + bytes, qd->ld.token_ex_len); bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len); /* password encrypted */ bytes += qq_put16(raw_data + bytes, encrypted_len); bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); - /* some random data */ - bytes += qq_put16(raw_data + bytes, 0x0014); - bytes += qq_put32(raw_data + bytes, rand() & 0xffff); - bytes += qq_put32(raw_data + bytes, rand() & 0xffff); - bytes += qq_put32(raw_data + bytes, rand() & 0xffff); - bytes += qq_put32(raw_data + bytes, rand() & 0xffff); - bytes += qq_put32(raw_data + bytes, rand() & 0xffff); + /* random data, 20 bytes */ + bytes += qq_put16(raw_data + bytes, 0x0014); /* length of next segment*/ + count = 0x14; + while (count--) bytes += qq_put8(raw_data + bytes, rand() & 0xff); /* put length into first 2 bytes */ qq_put16(raw_data, bytes - 2); /* tail */ - bytes += qq_put8(raw_data + bytes, 0); - bytes += qq_put8(raw_data + bytes, 0x03); + bytes += qq_put8(raw_data + bytes, 0); /* length of next segment */ + bytes += qq_put8(raw_data + bytes, 0x03); /* length of next segment */ bytes += qq_put8(raw_data + bytes, 0); - bytes += qq_put8(raw_data + bytes, qd->ld.pwd_2nd_md5[1]); - bytes += qq_put8(raw_data + bytes, qd->ld.pwd_2nd_md5[2]); - + bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[1]); + bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[2]); + qq_show_packet("QQ", raw_data, bytes); /* Encrypted by random key*/ - encrypted_len = qq_encrypt(encrypted, raw_data, QQ_LOGIN_DATA_LENGTH, qd->ld.random_key); + encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); buf = g_newa(guint8, MAX_PACKET_SIZE); memset(buf, 0, MAX_PACKET_SIZE); @@ -920,7 +938,7 @@ bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); + qq_send_cmd_encrypted(gc, QQ_CMD_CHECK_PWD, qd->send_seq, buf, bytes, TRUE); } guint8 qq_process_check_pwd_2007( PurpleConnection *gc, guint8 *data, gint data_len) @@ -960,7 +978,7 @@ switch (ret) { - case 0x34: /* invalid password */ + case 0x34: /* invalid password, 2nd byte is 0xc6 */ if (!purple_account_get_remember_password(gc->account)) { purple_account_set_password(gc->account, NULL); } @@ -987,13 +1005,13 @@ } qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, ">>> [default] decrypt and dump"); - bytes = 1; + bytes = 11; bytes += qq_get16(&msg_len, data + bytes); msg = g_strndup((gchar *)data + bytes, msg_len); msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); - purple_debug_error("QQ", "%s: %s\n", error, msg_utf8); + purple_debug_error("QQ", "%s:\n%s\n", error, msg_utf8); purple_connection_error_reason(gc, reason, msg_utf8); g_free(error); @@ -1100,39 +1118,37 @@ /* Encrypted password and put in encrypted */ bytes = 0; - bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_2nd_md5, sizeof(qd->ld.pwd_2nd_md5)); + bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); bytes += qq_put16(raw_data + bytes, 0); - bytes += qq_put16(raw_data + bytes, (guint16) (rand() & 0xffff)); + bytes += qq_put16(raw_data + bytes, rand() & 0xffff); - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_4th_md5); + encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); /* create packet */ bytes = 0; bytes += qq_putdata(raw_data + bytes, header, sizeof(header)); /* token get from qq_request_token_ex */ - bytes += qq_put16(raw_data + bytes, qd->ld.token_ex_len); + bytes += qq_put8(raw_data + bytes, qd->ld.token_ex_len); bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len); - bytes += qq_put8(raw_data + bytes, 0); /* password encrypted */ bytes += qq_put16(raw_data + bytes, encrypted_len); bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); - bytes += qq_put8(raw_data + bytes, 0); /* len of unknown + len of CRC32 */ - bytes += qq_put8(raw_data + bytes, sizeof(unknown) + 4); + bytes += qq_put16(raw_data + bytes, sizeof(unknown) + 4); bytes += qq_putdata(raw_data + bytes, unknown, sizeof(unknown)); bytes += qq_put32( raw_data + bytes, crc32(0xFFFFFFFF, unknown, sizeof(unknown))); /* put length into first 2 bytes */ qq_put16(raw_data, bytes - 2); /* tail */ - bytes += qq_put8(raw_data + bytes, 0); - bytes += qq_put8(raw_data + bytes, 0x03); + bytes += qq_put16(raw_data + bytes, 0x0003); bytes += qq_put8(raw_data + bytes, 0); - bytes += qq_put8(raw_data + bytes, qd->ld.pwd_2nd_md5[1]); - bytes += qq_put8(raw_data + bytes, qd->ld.pwd_2nd_md5[2]); + bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[1]); + bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[2]); + qq_show_packet("Check password", raw_data, bytes); /* Encrypted by random key*/ - encrypted_len = qq_encrypt(encrypted, raw_data, QQ_LOGIN_DATA_LENGTH, qd->ld.random_key); + encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); buf = g_newa(guint8, MAX_PACKET_SIZE); memset(buf, 0, MAX_PACKET_SIZE); @@ -1141,7 +1157,7 @@ bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); qd->send_seq++; - qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); + qq_send_cmd_encrypted(gc, QQ_CMD_CHECK_PWD, qd->send_seq, buf, bytes, TRUE); } void qq_request_login_2007(PurpleConnection *gc) @@ -1184,11 +1200,11 @@ /* Encrypted password and put in encrypted */ bytes = 0; - bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_2nd_md5, sizeof(qd->ld.pwd_2nd_md5)); + bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); bytes += qq_put16(raw_data + bytes, 0); bytes += qq_put16(raw_data + bytes, 0xffff); - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_4th_md5); + encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); /* create packet */ bytes = 0; @@ -1196,8 +1212,8 @@ /* password encrypted */ bytes += qq_put16(raw_data + bytes, encrypted_len); bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); - /* put data which NULL string encrypted by key pwd_4th_md5 */ - encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_4th_md5); + /* put data which NULL string encrypted by key pwd_twice_md5 */ + encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5); g_return_if_fail(encrypted_len == 16); bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); /* unknow fill */ @@ -1337,11 +1353,11 @@ /* Encrypted password and put in encrypted */ bytes = 0; - bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_2nd_md5, sizeof(qd->ld.pwd_2nd_md5)); + bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); bytes += qq_put16(raw_data + bytes, 0); bytes += qq_put16(raw_data + bytes, 0xffff); - encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_4th_md5); + encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); /* create packet */ bytes = 0; @@ -1350,8 +1366,8 @@ /* password encrypted */ bytes += qq_put16(raw_data + bytes, encrypted_len); bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); - /* put data which NULL string encrypted by key pwd_4th_md5 */ - encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_4th_md5); + /* put data which NULL string encrypted by key pwd_twice_md5 */ + encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5); g_return_if_fail(encrypted_len == 16); bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); /* unknow 19 bytes zero filled*/
--- a/libpurple/protocols/qq/qq_network.c Wed Oct 22 14:40:04 2008 +0000 +++ b/libpurple/protocols/qq/qq_network.c Wed Oct 22 14:41:13 2008 +0000 @@ -309,6 +309,8 @@ switch (cmd) { case QQ_CMD_TOKEN: case QQ_CMD_GET_SERVER: + case QQ_CMD_TOKEN_EX: + case QQ_CMD_CHECK_PWD: case QQ_CMD_LOGIN: ret = qq_proc_login_cmds(gc, cmd, seq, buf + bytes, bytes_not_read, update_class, ship32); if (ret != QQ_LOGIN_REPLY_OK) { @@ -715,13 +717,11 @@ passwd = purple_account_get_password(purple_connection_get_account(gc)); /* use twice-md5 of user password as session key since QQ 2003iii */ - dest = qd->ld.pwd_2nd_md5; + dest = qd->ld.pwd_md5; qq_get_md5(dest, dest_len, (guint8 *)passwd, strlen(passwd)); - qq_get_md5(dest, dest_len, dest, dest_len); - dest = qd->ld.pwd_4th_md5; - qq_get_md5(dest, dest_len, qd->ld.pwd_2nd_md5, dest_len); - qq_get_md5(dest, dest_len, dest, dest_len); + dest = qd->ld.pwd_twice_md5; + qq_get_md5(dest, dest_len, qd->ld.pwd_md5, dest_len); } /* the callback function after socket is built @@ -1021,8 +1021,8 @@ qq_trans_remove_all(gc); memset(qd->ld.random_key, 0, sizeof(qd->ld.random_key)); - memset(qd->ld.pwd_2nd_md5, 0, sizeof(qd->ld.pwd_2nd_md5)); - memset(qd->ld.pwd_4th_md5, 0, sizeof(qd->ld.pwd_4th_md5)); + memset(qd->ld.pwd_md5, 0, sizeof(qd->ld.pwd_md5)); + memset(qd->ld.pwd_twice_md5, 0, sizeof(qd->ld.pwd_twice_md5)); memset(qd->ld.login_key, 0, sizeof(qd->ld.login_key)); memset(qd->session_key, 0, sizeof(qd->session_key)); memset(qd->session_md5, 0, sizeof(qd->session_md5));
--- a/libpurple/protocols/qq/qq_process.c Wed Oct 22 14:40:04 2008 +0000 +++ b/libpurple/protocols/qq/qq_process.c Wed Oct 22 14:41:13 2008 +0000 @@ -607,18 +607,18 @@ if (data_len >= 0) { purple_debug_warning("QQ", "Decrypt login packet by random_key, %d bytes\n", data_len); } else { - data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.pwd_4th_md5); + data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.pwd_twice_md5); if (data_len >= 0) { - purple_debug_warning("QQ", "Decrypt login packet by pwd_4th_md5, %d bytes\n", data_len); + purple_debug_warning("QQ", "Decrypt login packet by pwd_twice_md5, %d bytes\n", data_len); } } break; case QQ_CMD_LOGIN: default: if (qd->client_version > 2005) { - data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.pwd_4th_md5); + data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.pwd_twice_md5); if (data_len >= 0) { - purple_debug_warning("QQ", "Decrypt login packet by pwd_4th_md5\n"); + purple_debug_warning("QQ", "Decrypt login packet by pwd_twice_md5\n"); } else { data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.login_key); if (data_len >= 0) { @@ -631,9 +631,9 @@ if (data_len >= 0) { purple_debug_warning("QQ", "Decrypt login packet by random_key\n"); } else { - data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.pwd_2nd_md5); + data_len = qq_decrypt(data, rcved, rcved_len, qd->ld.pwd_twice_md5); if (data_len >= 0) { - purple_debug_warning("QQ", "Decrypt login packet by pwd_2nd_md5\n"); + purple_debug_warning("QQ", "Decrypt login packet by pwd_twice_md5\n"); } } }