| 68 0x40, 0xb8, 0xac, 0x32, 0x01 |
68 0x40, 0xb8, 0xac, 0x32, 0x01 |
| 69 }; |
69 }; |
| 70 */ |
70 */ |
| 71 |
71 |
| 72 /* for QQ 2005? copy from lumaqq */ |
72 /* for QQ 2005? copy from lumaqq */ |
| 73 // Fixme: change to guint8 |
73 /* FIXME: change to guint8 */ |
| 74 static const guint8 login_23_51[29] = { |
74 static const guint8 login_23_51[29] = { |
| 75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 76 0x00, 0x00, 0x00, 0x00, 0x86, 0xcc, 0x4c, 0x35, |
76 0x00, 0x00, 0x00, 0x00, 0x86, 0xcc, 0x4c, 0x35, |
| 77 0x2c, 0xd3, 0x73, 0x6c, 0x14, 0xf6, 0xf6, 0xaf, |
77 0x2c, 0xd3, 0x73, 0x6c, 0x14, 0xf6, 0xf6, 0xaf, |
| 78 0xc3, 0xfa, 0x33, 0xa4, 0x01 |
78 0xc3, 0xfa, 0x33, 0xa4, 0x01 |
| 148 guint8 *src, md5_str[QQ_KEY_LENGTH]; |
148 guint8 *src, md5_str[QQ_KEY_LENGTH]; |
| 149 PurpleCipher *cipher; |
149 PurpleCipher *cipher; |
| 150 PurpleCipherContext *context; |
150 PurpleCipherContext *context; |
| 151 |
151 |
| 152 src = g_newa(guint8, 20); |
152 src = g_newa(guint8, 20); |
| 153 memcpy(src, &uid, 4); |
153 /* bug found by QuLogic */ |
| 154 memcpy(src, session_key, QQ_KEY_LENGTH); |
154 memcpy(src, &uid, sizeof(uid)); |
| |
155 memcpy(src + sizeof(uid), session_key, QQ_KEY_LENGTH); |
| 155 |
156 |
| 156 cipher = purple_ciphers_find_cipher("md5"); |
157 cipher = purple_ciphers_find_cipher("md5"); |
| 157 context = purple_cipher_context_new(cipher, NULL); |
158 context = purple_cipher_context_new(cipher, NULL); |
| 158 purple_cipher_context_append(context, src, 20); |
159 purple_cipher_context_append(context, src, 20); |
| 159 purple_cipher_context_digest(context, sizeof(md5_str), md5_str, NULL); |
160 purple_cipher_context_digest(context, sizeof(md5_str), md5_str, NULL); |
| 168 gint bytes; |
169 gint bytes; |
| 169 qq_data *qd; |
170 qq_data *qd; |
| 170 qq_login_reply_ok_packet lrop; |
171 qq_login_reply_ok_packet lrop; |
| 171 |
172 |
| 172 qd = (qq_data *) gc->proto_data; |
173 qd = (qq_data *) gc->proto_data; |
| |
174 /* FIXME, check QQ_LOGIN_REPLY_OK_PACKET_LEN here */ |
| 173 bytes = 0; |
175 bytes = 0; |
| 174 |
176 |
| 175 /* 000-000: reply code */ |
177 /* 000-000: reply code */ |
| 176 bytes += qq_get8(&lrop.result, data + bytes); |
178 bytes += qq_get8(&lrop.result, data + bytes); |
| 177 /* 001-016: session key */ |
179 /* 001-016: session key */ |
| 279 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
281 purple_debug(PURPLE_DEBUG_ERROR, "QQ", |
| 280 "Fail parsing login redirect packet, expect %d bytes, read %d bytes\n", |
282 "Fail parsing login redirect packet, expect %d bytes, read %d bytes\n", |
| 281 QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN, bytes); |
283 QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN, bytes); |
| 282 ret = QQ_LOGIN_REPLY_MISC_ERROR; |
284 ret = QQ_LOGIN_REPLY_MISC_ERROR; |
| 283 } else { |
285 } else { |
| 284 // redirect to new server, do not disconnect or connect here |
286 /* redirect to new server, do not disconnect or connect here |
| 285 // those connect should be called at packet_process |
287 * those connect should be called at packet_process */ |
| 286 if (qd->real_hostname) { |
288 if (qd->real_hostname) { |
| 287 purple_debug(PURPLE_DEBUG_INFO, "QQ", "free real_hostname\n"); |
289 purple_debug(PURPLE_DEBUG_INFO, "QQ", "free real_hostname\n"); |
| 288 g_free(qd->real_hostname); |
290 g_free(qd->real_hostname); |
| 289 qd->real_hostname = NULL; |
291 qd->real_hostname = NULL; |
| 290 } |
292 } |
| 325 g_return_if_fail(gc != NULL && gc->proto_data != NULL); |
327 g_return_if_fail(gc != NULL && gc->proto_data != NULL); |
| 326 qd = (qq_data *) gc->proto_data; |
328 qd = (qq_data *) gc->proto_data; |
| 327 |
329 |
| 328 bytes += qq_put8(buf + bytes, 0); |
330 bytes += qq_put8(buf + bytes, 0); |
| 329 |
331 |
| 330 qq_send_data(gc, QQ_CMD_REQUEST_LOGIN_TOKEN, buf, bytes); |
332 qq_send_data(qd, QQ_CMD_REQUEST_LOGIN_TOKEN, buf, bytes); |
| 331 } |
333 } |
| 332 |
334 |
| 333 /* send login packet to QQ server */ |
335 /* send login packet to QQ server */ |
| 334 static void qq_send_packet_login(PurpleConnection *gc, guint8 token_length, guint8 *token) |
336 static void qq_send_packet_login(PurpleConnection *gc, guint8 token_length, guint8 *token) |
| 335 { |
337 { |
| 382 memset(buf, 0, MAX_PACKET_SIZE); |
384 memset(buf, 0, MAX_PACKET_SIZE); |
| 383 bytes = 0; |
385 bytes = 0; |
| 384 bytes += qq_putdata(buf + bytes, qd->inikey, QQ_KEY_LENGTH); |
386 bytes += qq_putdata(buf + bytes, qd->inikey, QQ_KEY_LENGTH); |
| 385 bytes += qq_putdata(buf + bytes, encrypted_data, encrypted_len); |
387 bytes += qq_putdata(buf + bytes, encrypted_data, encrypted_len); |
| 386 |
388 |
| 387 qq_send_data(gc, QQ_CMD_LOGIN, buf, bytes); |
389 qq_send_data(qd, QQ_CMD_LOGIN, buf, bytes); |
| 388 } |
390 } |
| 389 |
391 |
| 390 void qq_process_request_login_token_reply(guint8 *buf, gint buf_len, PurpleConnection *gc) |
392 void qq_process_request_login_token_reply(guint8 *buf, gint buf_len, PurpleConnection *gc) |
| 391 { |
393 { |
| 392 qq_data *qd; |
394 qq_data *qd; |
| 429 gint i; |
431 gint i; |
| 430 qq_data *qd; |
432 qq_data *qd; |
| 431 |
433 |
| 432 qd = (qq_data *) gc->proto_data; |
434 qd = (qq_data *) gc->proto_data; |
| 433 for (i = 0; i < 4; i++) |
435 for (i = 0; i < 4; i++) |
| 434 qq_send_cmd(gc, QQ_CMD_LOGOUT, FALSE, 0xffff, FALSE, qd->pwkey, QQ_KEY_LENGTH); |
436 qq_send_cmd_detail(qd, QQ_CMD_LOGOUT, 0xffff, FALSE, qd->pwkey, QQ_KEY_LENGTH); |
| 435 |
437 |
| 436 qd->logged_in = FALSE; /* update login status AFTER sending logout packets */ |
438 qd->logged_in = FALSE; /* update login status AFTER sending logout packets */ |
| 437 } |
439 } |
| 438 |
440 |
| 439 /* process the login reply packet */ |
441 /* process the login reply packet */ |