| 69 struct tm *tm_local; |
66 struct tm *tm_local; |
| 70 |
67 |
| 71 qd = (qq_data *) gc->proto_data; |
68 qd = (qq_data *) gc->proto_data; |
| 72 qq_show_packet("Login reply", data, len); |
69 qq_show_packet("Login reply", data, len); |
| 73 |
70 |
| 74 /* FIXME, check QQ_LOGIN_REPLY_OK_PACKET_LEN here */ |
71 if (len < 139) { |
| |
72 purple_connection_error_reason(gc, |
| |
73 PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, |
| |
74 _("Can not decrypt get server reply")); |
| |
75 return QQ_LOGIN_REPLY_ERR; |
| |
76 } |
| |
77 |
| 75 bytes = 0; |
78 bytes = 0; |
| 76 bytes += qq_get8(&ret, data + bytes); |
79 bytes += qq_get8(&ret, data + bytes); |
| 77 bytes += qq_getdata(qd->session_key, sizeof(qd->session_key), data + bytes); |
80 bytes += qq_getdata(qd->session_key, sizeof(qd->session_key), data + bytes); |
| 78 get_session_md5(qd->session_md5, qd->uid, qd->session_key); |
81 get_session_md5(qd->session_md5, qd->uid, qd->session_key); |
| 79 purple_debug_info("QQ", "Got session_key\n"); |
82 purple_debug_info("QQ", "Got session_key\n"); |
| 132 purple_debug_info("QQ", "Time: %d-%d-%d, %d:%d:%d\n", |
135 purple_debug_info("QQ", "Time: %d-%d-%d, %d:%d:%d\n", |
| 133 (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, |
136 (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, |
| 134 tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); |
137 tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); |
| 135 /* unknow 9 bytes, 0x(00 0a 00 0a 01 00 00 0e 10) */ |
138 /* unknow 9 bytes, 0x(00 0a 00 0a 01 00 00 0e 10) */ |
| 136 |
139 |
| 137 if (bytes != QQ_LOGIN_REPLY_OK_PACKET_LEN) { /* fail parsing login info */ |
140 if (len > 139) { |
| 138 purple_debug_warning("QQ", |
141 purple_debug_warning("QQ", "Login reply more than expected %d bytes, read %d bytes\n", 139, bytes); |
| 139 "Fail parsing login info, expect %d bytes, read %d bytes\n", |
142 } |
| 140 QQ_LOGIN_REPLY_OK_PACKET_LEN, bytes); |
|
| 141 } /* but we still go on as login OK */ |
|
| 142 return QQ_LOGIN_REPLY_OK; |
143 return QQ_LOGIN_REPLY_OK; |
| 143 } |
144 } |
| 144 |
145 |
| 145 /* process login reply packet which includes redirected new server address */ |
146 /* process login reply packet which includes redirected new server address */ |
| 146 static gint8 process_login_redirect(PurpleConnection *gc, guint8 *data, gint len) |
147 static gint8 process_login_redirect(PurpleConnection *gc, guint8 *data, gint len) |
| 164 /* 005-008: redirected new server IP */ |
172 /* 005-008: redirected new server IP */ |
| 165 bytes += qq_getIP(&packet.new_server_ip, data + bytes); |
173 bytes += qq_getIP(&packet.new_server_ip, data + bytes); |
| 166 /* 009-010: redirected new server port */ |
174 /* 009-010: redirected new server port */ |
| 167 bytes += qq_get16(&packet.new_server_port, data + bytes); |
175 bytes += qq_get16(&packet.new_server_port, data + bytes); |
| 168 |
176 |
| 169 if (bytes != QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN) { |
177 if (len > 11) { |
| 170 purple_debug_error("QQ", |
178 purple_debug_error("QQ", "Login redirect more than expected %d bytes, read %d bytes\n", 11, bytes); |
| 171 "Fail parsing login redirect packet, expect %d bytes, read %d bytes\n", |
|
| 172 QQ_LOGIN_REPLY_REDIRECT_PACKET_LEN, bytes); |
|
| 173 return QQ_LOGIN_REPLY_ERR; |
|
| 174 } |
179 } |
| 175 |
180 |
| 176 /* redirect to new server, do not disconnect or connect here |
181 /* redirect to new server, do not disconnect or connect here |
| 177 * those connect should be called at packet_process */ |
182 * those connect should be called at packet_process */ |
| 178 qd->redirect_ip.s_addr = packet.new_server_ip.s_addr; |
183 qd->redirect_ip.s_addr = packet.new_server_ip.s_addr; |
| 237 g_return_if_fail(gc != NULL && gc->proto_data != NULL); |
242 g_return_if_fail(gc != NULL && gc->proto_data != NULL); |
| 238 qd = (qq_data *) gc->proto_data; |
243 qd = (qq_data *) gc->proto_data; |
| 239 |
244 |
| 240 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); |
245 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); |
| 241 |
246 |
| 242 raw_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH); |
247 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16); |
| 243 memset(raw_data, 0, QQ_LOGIN_DATA_LENGTH); |
248 memset(raw_data, 0, MAX_PACKET_SIZE - 16); |
| 244 |
249 |
| 245 encrypted = g_newa(guint8, QQ_LOGIN_DATA_LENGTH + 16); /* 16 bytes more */ |
250 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ |
| 246 |
251 |
| 247 bytes = 0; |
252 bytes = 0; |
| 248 /* now generate the encrypted data |
253 /* now generate the encrypted data |
| 249 * 000-015 use password_twice_md5 as key to encrypt empty string */ |
254 * 000-015 use password_twice_md5 as key to encrypt empty string */ |
| 250 encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_2nd_md5); |
255 encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5); |
| 251 g_return_if_fail(encrypted_len == 16); |
256 g_return_if_fail(encrypted_len == 16); |
| 252 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
257 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
| 253 |
258 |
| 254 /* 016-016 */ |
259 /* 016-016 */ |
| 255 bytes += qq_put8(raw_data + bytes, 0x00); |
260 bytes += qq_put8(raw_data + bytes, 0x00); |
| 268 /* 070-093, login token, normally 24 bytes */ |
273 /* 070-093, login token, normally 24 bytes */ |
| 269 bytes += qq_putdata(raw_data + bytes, qd->ld.token, qd->ld.token_len); |
274 bytes += qq_putdata(raw_data + bytes, qd->ld.token, qd->ld.token_len); |
| 270 /* 100 bytes unknown */ |
275 /* 100 bytes unknown */ |
| 271 bytes += qq_putdata(raw_data + bytes, login_100_bytes, 100); |
276 bytes += qq_putdata(raw_data + bytes, login_100_bytes, 100); |
| 272 /* all zero left */ |
277 /* all zero left */ |
| 273 |
278 memset(raw_data + bytes, 0, 416 - bytes); |
| 274 encrypted_len = qq_encrypt(encrypted, raw_data, QQ_LOGIN_DATA_LENGTH, qd->ld.random_key); |
279 bytes = 416; |
| |
280 |
| |
281 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); |
| 275 |
282 |
| 276 buf = g_newa(guint8, MAX_PACKET_SIZE); |
283 buf = g_newa(guint8, MAX_PACKET_SIZE); |
| 277 memset(buf, 0, MAX_PACKET_SIZE); |
284 memset(buf, 0, MAX_PACKET_SIZE); |
| 278 bytes = 0; |
285 bytes = 0; |
| 279 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); |
286 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); |
| 500 gint encrypted_len; |
507 gint encrypted_len; |
| 501 |
508 |
| 502 g_return_if_fail(gc != NULL && gc->proto_data != NULL); |
509 g_return_if_fail(gc != NULL && gc->proto_data != NULL); |
| 503 qd = (qq_data *) gc->proto_data; |
510 qd = (qq_data *) gc->proto_data; |
| 504 |
511 |
| 505 raw_data = g_newa(guint8, QQ_LOGIN_DATA_LENGTH); |
512 raw_data = g_newa(guint8, sizeof(qd->redirect_data)); |
| 506 memset(raw_data, 0, QQ_LOGIN_DATA_LENGTH); |
513 memset(raw_data, 0, sizeof(qd->redirect_data)); |
| 507 |
514 |
| 508 encrypted = g_newa(guint8, QQ_LOGIN_DATA_LENGTH + 16); /* 16 bytes more */ |
515 encrypted = g_newa(guint8, sizeof(qd->redirect_data) + 16); /* 16 bytes more */ |
| 509 |
516 |
| 510 bytes = 0; |
517 bytes = 0; |
| 511 bytes += qq_putdata(raw_data + bytes, (guint8 *)&qd->redirect_data, sizeof(qd->redirect_data)); |
518 bytes += qq_put16(raw_data + bytes, qd->redirect_data.ret); |
| 512 |
519 bytes += qq_put8(raw_data + bytes, qd->redirect_data.b1); |
| 513 encrypted_len = qq_encrypt(encrypted, raw_data, QQ_LOGIN_DATA_LENGTH, qd->ld.random_key); |
520 bytes += qq_put32(raw_data + bytes, qd->redirect_data.w1); |
| |
521 bytes += qq_put32(raw_data + bytes, qd->redirect_data.w2); |
| |
522 bytes += qq_putIP(raw_data + bytes, &(qd->redirect_data.ip)); |
| |
523 |
| |
524 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); |
| 514 |
525 |
| 515 buf = g_newa(guint8, MAX_PACKET_SIZE); |
526 buf = g_newa(guint8, MAX_PACKET_SIZE); |
| 516 memset(buf, 0, MAX_PACKET_SIZE); |
527 memset(buf, 0, MAX_PACKET_SIZE); |
| 517 bytes = 0; |
528 bytes = 0; |
| 518 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); |
529 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); |
| 519 bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); |
530 bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); |
| 520 |
531 |
| 521 qd->send_seq++; |
532 qd->send_seq++; |
| 522 qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); |
533 qq_send_cmd_encrypted(gc, QQ_CMD_GET_SERVER, qd->send_seq, buf, bytes, TRUE); |
| 523 } |
534 } |
| 524 |
535 |
| 525 guint16 qq_process_get_server(PurpleConnection *gc, guint8 *data, gint data_len) |
536 guint16 qq_process_get_server(PurpleConnection *gc, guint8 *data, gint data_len) |
| 526 { |
537 { |
| 527 qq_data *qd; |
538 qq_data *qd; |
| 528 qq_redirect_data *redirect; |
539 gint bytes; |
| 529 |
540 |
| 530 g_return_val_if_fail (gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR); |
541 g_return_val_if_fail (gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR); |
| 531 qd = (qq_data *) gc->proto_data; |
542 qd = (qq_data *) gc->proto_data; |
| 532 |
543 |
| 533 g_return_val_if_fail (data != NULL, QQ_LOGIN_REPLY_ERR); |
544 g_return_val_if_fail (data != NULL, QQ_LOGIN_REPLY_ERR); |
| 534 if (data_len < sizeof(qq_redirect_data)) { |
545 |
| 535 purple_connection_error_reason(gc, |
546 /* qq_show_packet("Get Server", data, data_len); */ |
| 536 PURPLE_CONNECTION_ERROR_NETWORK_ERROR, |
547 bytes = 0; |
| 537 _("Can not decrypt get server reply")); |
548 bytes += qq_get16(&qd->redirect_data.ret, data + bytes); |
| 538 return QQ_LOGIN_REPLY_ERR; |
549 if (qd->redirect_data.ret == 0) { |
| 539 } |
|
| 540 |
|
| 541 redirect = (qq_redirect_data *)data; |
|
| 542 if (redirect->ret == 0) { |
|
| 543 memset(&qd->redirect_data, 0, sizeof(qd->redirect_data)); |
550 memset(&qd->redirect_data, 0, sizeof(qd->redirect_data)); |
| 544 qd->redirect_ip.s_addr = 0; |
551 qd->redirect_ip.s_addr = 0; |
| 545 return QQ_LOGIN_REPLY_OK; |
552 return QQ_LOGIN_REPLY_OK; |
| 546 } |
553 } |
| 547 |
554 |
| 548 g_memmove(&qd->redirect_data, redirect, sizeof(qd->redirect_data)); |
555 if (data_len < 15) { |
| 549 g_memmove(&qd->redirect_ip, &redirect->ip, sizeof(qd->redirect_ip)); |
556 purple_connection_error_reason(gc, |
| |
557 PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, |
| |
558 _("Can not decrypt get server reply")); |
| |
559 return QQ_LOGIN_REPLY_ERR; |
| |
560 } |
| |
561 |
| |
562 bytes += qq_get8(&qd->redirect_data.b1, data + bytes); |
| |
563 bytes += qq_get32(&qd->redirect_data.w1, data + bytes); |
| |
564 bytes += qq_get32(&qd->redirect_data.w2, data + bytes); |
| |
565 bytes += qq_getIP(&qd->redirect_data.ip, data + bytes); |
| |
566 purple_debug_info("QQ", "Get server %d-%d-%d%d, %s\n", |
| |
567 qd->redirect_data.ret, qd->redirect_data.b1, qd->redirect_data.w1, qd->redirect_data.w2, |
| |
568 inet_ntoa(qd->redirect_data.ip)); |
| |
569 |
| |
570 g_memmove(&qd->redirect_ip, &qd->redirect_data.ip, sizeof(qd->redirect_ip)); |
| 550 return QQ_LOGIN_REPLY_REDIRECT; |
571 return QQ_LOGIN_REPLY_REDIRECT; |
| 551 } |
572 } |
| 552 |
573 |
| 553 void qq_request_token_ex(PurpleConnection *gc) |
574 void qq_request_token_ex(PurpleConnection *gc) |
| 554 { |
575 { |
| 575 bytes += qq_put16(raw_data + bytes, 5); |
596 bytes += qq_put16(raw_data + bytes, 5); |
| 576 bytes += qq_put32(raw_data + bytes, 0); |
597 bytes += qq_put32(raw_data + bytes, 0); |
| 577 bytes += qq_put8(raw_data + bytes, 0); /* fragment index */ |
598 bytes += qq_put8(raw_data + bytes, 0); /* fragment index */ |
| 578 bytes += qq_put16(raw_data + bytes, 0); /* captcha token */ |
599 bytes += qq_put16(raw_data + bytes, 0); /* captcha token */ |
| 579 |
600 |
| 580 encrypted_len = qq_encrypt(encrypted, raw_data, QQ_LOGIN_DATA_LENGTH, qd->ld.random_key); |
601 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); |
| 581 |
602 |
| 582 buf = g_newa(guint8, MAX_PACKET_SIZE); |
603 buf = g_newa(guint8, MAX_PACKET_SIZE); |
| 583 memset(buf, 0, MAX_PACKET_SIZE); |
604 memset(buf, 0, MAX_PACKET_SIZE); |
| 584 bytes = 0; |
605 bytes = 0; |
| 585 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); |
606 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); |
| 615 bytes += qq_put32(raw_data + bytes, 0); |
636 bytes += qq_put32(raw_data + bytes, 0); |
| 616 bytes += qq_put8(raw_data + bytes, qd->captcha.next_index); /* fragment index */ |
637 bytes += qq_put8(raw_data + bytes, qd->captcha.next_index); /* fragment index */ |
| 617 bytes += qq_put16(raw_data + bytes, qd->captcha.token_len); /* captcha token */ |
638 bytes += qq_put16(raw_data + bytes, qd->captcha.token_len); /* captcha token */ |
| 618 bytes += qq_putdata(raw_data + bytes, qd->captcha.token, qd->captcha.token_len); |
639 bytes += qq_putdata(raw_data + bytes, qd->captcha.token, qd->captcha.token_len); |
| 619 |
640 |
| 620 encrypted_len = qq_encrypt(encrypted, raw_data, QQ_LOGIN_DATA_LENGTH, qd->ld.random_key); |
641 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); |
| 621 |
642 |
| 622 buf = g_newa(guint8, MAX_PACKET_SIZE); |
643 buf = g_newa(guint8, MAX_PACKET_SIZE); |
| 623 memset(buf, 0, MAX_PACKET_SIZE); |
644 memset(buf, 0, MAX_PACKET_SIZE); |
| 624 bytes = 0; |
645 bytes = 0; |
| 625 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); |
646 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); |
| 660 bytes += qq_put16(raw_data + bytes, code_len); |
681 bytes += qq_put16(raw_data + bytes, code_len); |
| 661 bytes += qq_putdata(raw_data + bytes, code, code_len); |
682 bytes += qq_putdata(raw_data + bytes, code, code_len); |
| 662 bytes += qq_put16(raw_data + bytes, qd->captcha.token_len); /* captcha token */ |
683 bytes += qq_put16(raw_data + bytes, qd->captcha.token_len); /* captcha token */ |
| 663 bytes += qq_putdata(raw_data + bytes, qd->captcha.token, qd->captcha.token_len); |
684 bytes += qq_putdata(raw_data + bytes, qd->captcha.token, qd->captcha.token_len); |
| 664 |
685 |
| 665 encrypted_len = qq_encrypt(encrypted, raw_data, QQ_LOGIN_DATA_LENGTH, qd->ld.random_key); |
686 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); |
| 666 |
687 |
| 667 buf = g_newa(guint8, MAX_PACKET_SIZE); |
688 buf = g_newa(guint8, MAX_PACKET_SIZE); |
| 668 memset(buf, 0, MAX_PACKET_SIZE); |
689 memset(buf, 0, MAX_PACKET_SIZE); |
| 669 bytes = 0; |
690 bytes = 0; |
| 670 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); |
691 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); |
| 781 qd = (qq_data *) gc->proto_data; |
802 qd = (qq_data *) gc->proto_data; |
| 782 |
803 |
| 783 ret = data[0]; |
804 ret = data[0]; |
| 784 |
805 |
| 785 bytes = 0; |
806 bytes = 0; |
| 786 bytes += qq_get8(&sub_cmd, data + bytes); |
807 bytes += qq_get8(&sub_cmd, data + bytes); /* 03: ok; 04: need verifying */ |
| 787 bytes += 2; |
808 bytes += 2; /* 0x(00 05) */ |
| 788 bytes += qq_get8(&reply, data + bytes); |
809 bytes += qq_get8(&reply, data + bytes); |
| 789 |
810 |
| 790 bytes += qq_get16(&(qd->ld.token_ex_len), data + bytes); |
811 bytes += qq_get16(&(qd->ld.token_ex_len), data + bytes); |
| 791 if (qd->ld.token_ex != NULL) g_free(qd->ld.token_ex); |
812 if (qd->ld.token_ex != NULL) g_free(qd->ld.token_ex); |
| 792 qd->ld.token_ex = g_new0(guint8, qd->ld.token_ex_len); |
813 qd->ld.token_ex = g_new0(guint8, qd->ld.token_ex_len); |
| 793 bytes += qq_getdata(qd->ld.token_ex, qd->ld.token_ex_len , data + bytes); |
814 bytes += qq_getdata(qd->ld.token_ex, qd->ld.token_ex_len , data + bytes); |
| 794 |
815 |
| 795 if(reply != 1) |
816 if(reply != 1) |
| 796 { |
817 { |
| 797 purple_debug_info("QQ", "Captcha verified\n"); |
818 purple_debug_info("QQ", "Captcha verified, result %d\n", reply); |
| 798 return QQ_LOGIN_REPLY_OK; |
819 return QQ_LOGIN_REPLY_OK; |
| 799 } |
820 } |
| 800 |
821 |
| 801 bytes += qq_get16(&captcha_len, data + bytes); |
822 bytes += qq_get16(&captcha_len, data + bytes); |
| 802 |
823 |
| 877 |
899 |
| 878 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ |
900 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ |
| 879 |
901 |
| 880 /* Encrypted password and put in encrypted */ |
902 /* Encrypted password and put in encrypted */ |
| 881 bytes = 0; |
903 bytes = 0; |
| 882 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_2nd_md5, sizeof(qd->ld.pwd_2nd_md5)); |
904 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); |
| 883 bytes += qq_put16(raw_data + bytes, 0); |
905 bytes += qq_put16(raw_data + bytes, rand() & 0); |
| 884 bytes += qq_put16(raw_data + bytes, 0); |
906 bytes += qq_put16(raw_data + bytes, rand() & 0xffff); |
| 885 |
907 |
| 886 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_4th_md5); |
908 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); |
| 887 |
|
| 888 /* create packet */ |
909 /* create packet */ |
| 889 bytes = 0; |
910 bytes = 0; |
| 890 bytes += qq_putdata(raw_data + bytes, header, sizeof(header)); |
911 bytes += qq_putdata(raw_data + bytes, header, sizeof(header)); |
| 891 /* token get from qq_process_token_ex */ |
912 /* token get from qq_process_token_ex */ |
| 892 bytes += qq_put16(raw_data + bytes, qd->ld.token_ex_len); |
913 bytes += qq_put8(raw_data + bytes, qd->ld.token_ex_len); |
| 893 bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len); |
914 bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len); |
| 894 /* password encrypted */ |
915 /* password encrypted */ |
| 895 bytes += qq_put16(raw_data + bytes, encrypted_len); |
916 bytes += qq_put16(raw_data + bytes, encrypted_len); |
| 896 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
917 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
| 897 /* some random data */ |
918 /* random data, 20 bytes */ |
| 898 bytes += qq_put16(raw_data + bytes, 0x0014); |
919 bytes += qq_put16(raw_data + bytes, 0x0014); /* length of next segment*/ |
| 899 bytes += qq_put32(raw_data + bytes, rand() & 0xffff); |
920 count = 0x14; |
| 900 bytes += qq_put32(raw_data + bytes, rand() & 0xffff); |
921 while (count--) bytes += qq_put8(raw_data + bytes, rand() & 0xff); |
| 901 bytes += qq_put32(raw_data + bytes, rand() & 0xffff); |
|
| 902 bytes += qq_put32(raw_data + bytes, rand() & 0xffff); |
|
| 903 bytes += qq_put32(raw_data + bytes, rand() & 0xffff); |
|
| 904 /* put length into first 2 bytes */ |
922 /* put length into first 2 bytes */ |
| 905 qq_put16(raw_data, bytes - 2); |
923 qq_put16(raw_data, bytes - 2); |
| 906 /* tail */ |
924 /* tail */ |
| |
925 bytes += qq_put8(raw_data + bytes, 0); /* length of next segment */ |
| |
926 bytes += qq_put8(raw_data + bytes, 0x03); /* length of next segment */ |
| 907 bytes += qq_put8(raw_data + bytes, 0); |
927 bytes += qq_put8(raw_data + bytes, 0); |
| 908 bytes += qq_put8(raw_data + bytes, 0x03); |
928 bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[1]); |
| 909 bytes += qq_put8(raw_data + bytes, 0); |
929 bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[2]); |
| 910 bytes += qq_put8(raw_data + bytes, qd->ld.pwd_2nd_md5[1]); |
930 qq_show_packet("QQ", raw_data, bytes); |
| 911 bytes += qq_put8(raw_data + bytes, qd->ld.pwd_2nd_md5[2]); |
|
| 912 |
|
| 913 /* Encrypted by random key*/ |
931 /* Encrypted by random key*/ |
| 914 encrypted_len = qq_encrypt(encrypted, raw_data, QQ_LOGIN_DATA_LENGTH, qd->ld.random_key); |
932 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); |
| 915 |
933 |
| 916 buf = g_newa(guint8, MAX_PACKET_SIZE); |
934 buf = g_newa(guint8, MAX_PACKET_SIZE); |
| 917 memset(buf, 0, MAX_PACKET_SIZE); |
935 memset(buf, 0, MAX_PACKET_SIZE); |
| 918 bytes = 0; |
936 bytes = 0; |
| 919 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); |
937 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); |
| 920 bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); |
938 bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); |
| 921 |
939 |
| 922 qd->send_seq++; |
940 qd->send_seq++; |
| 923 qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); |
941 qq_send_cmd_encrypted(gc, QQ_CMD_CHECK_PWD, qd->send_seq, buf, bytes, TRUE); |
| 924 } |
942 } |
| 925 |
943 |
| 926 guint8 qq_process_check_pwd_2007( PurpleConnection *gc, guint8 *data, gint data_len) |
944 guint8 qq_process_check_pwd_2007( PurpleConnection *gc, guint8 *data, gint data_len) |
| 927 { |
945 { |
| 928 qq_data *qd; |
946 qq_data *qd; |
| 985 reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR; |
1003 reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR; |
| 986 break; |
1004 break; |
| 987 } |
1005 } |
| 988 qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, |
1006 qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, |
| 989 ">>> [default] decrypt and dump"); |
1007 ">>> [default] decrypt and dump"); |
| 990 bytes = 1; |
1008 bytes = 11; |
| 991 bytes += qq_get16(&msg_len, data + bytes); |
1009 bytes += qq_get16(&msg_len, data + bytes); |
| 992 |
1010 |
| 993 msg = g_strndup((gchar *)data + bytes, msg_len); |
1011 msg = g_strndup((gchar *)data + bytes, msg_len); |
| 994 msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); |
1012 msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); |
| 995 |
1013 |
| 996 purple_debug_error("QQ", "%s: %s\n", error, msg_utf8); |
1014 purple_debug_error("QQ", "%s:\n%s\n", error, msg_utf8); |
| 997 purple_connection_error_reason(gc, reason, msg_utf8); |
1015 purple_connection_error_reason(gc, reason, msg_utf8); |
| 998 |
1016 |
| 999 g_free(error); |
1017 g_free(error); |
| 1000 g_free(msg); |
1018 g_free(msg); |
| 1001 g_free(msg_utf8); |
1019 g_free(msg_utf8); |
| 1098 |
1116 |
| 1099 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ |
1117 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ |
| 1100 |
1118 |
| 1101 /* Encrypted password and put in encrypted */ |
1119 /* Encrypted password and put in encrypted */ |
| 1102 bytes = 0; |
1120 bytes = 0; |
| 1103 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_2nd_md5, sizeof(qd->ld.pwd_2nd_md5)); |
1121 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); |
| 1104 bytes += qq_put16(raw_data + bytes, 0); |
1122 bytes += qq_put16(raw_data + bytes, 0); |
| 1105 bytes += qq_put16(raw_data + bytes, (guint16) (rand() & 0xffff)); |
1123 bytes += qq_put16(raw_data + bytes, rand() & 0xffff); |
| 1106 |
1124 |
| 1107 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_4th_md5); |
1125 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); |
| 1108 |
1126 |
| 1109 /* create packet */ |
1127 /* create packet */ |
| 1110 bytes = 0; |
1128 bytes = 0; |
| 1111 bytes += qq_putdata(raw_data + bytes, header, sizeof(header)); |
1129 bytes += qq_putdata(raw_data + bytes, header, sizeof(header)); |
| 1112 /* token get from qq_request_token_ex */ |
1130 /* token get from qq_request_token_ex */ |
| 1113 bytes += qq_put16(raw_data + bytes, qd->ld.token_ex_len); |
1131 bytes += qq_put8(raw_data + bytes, qd->ld.token_ex_len); |
| 1114 bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len); |
1132 bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len); |
| 1115 bytes += qq_put8(raw_data + bytes, 0); |
|
| 1116 /* password encrypted */ |
1133 /* password encrypted */ |
| 1117 bytes += qq_put16(raw_data + bytes, encrypted_len); |
1134 bytes += qq_put16(raw_data + bytes, encrypted_len); |
| 1118 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
1135 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
| 1119 bytes += qq_put8(raw_data + bytes, 0); |
|
| 1120 /* len of unknown + len of CRC32 */ |
1136 /* len of unknown + len of CRC32 */ |
| 1121 bytes += qq_put8(raw_data + bytes, sizeof(unknown) + 4); |
1137 bytes += qq_put16(raw_data + bytes, sizeof(unknown) + 4); |
| 1122 bytes += qq_putdata(raw_data + bytes, unknown, sizeof(unknown)); |
1138 bytes += qq_putdata(raw_data + bytes, unknown, sizeof(unknown)); |
| 1123 bytes += qq_put32( |
1139 bytes += qq_put32( |
| 1124 raw_data + bytes, crc32(0xFFFFFFFF, unknown, sizeof(unknown))); |
1140 raw_data + bytes, crc32(0xFFFFFFFF, unknown, sizeof(unknown))); |
| 1125 /* put length into first 2 bytes */ |
1141 /* put length into first 2 bytes */ |
| 1126 qq_put16(raw_data, bytes - 2); |
1142 qq_put16(raw_data, bytes - 2); |
| 1127 /* tail */ |
1143 /* tail */ |
| |
1144 bytes += qq_put16(raw_data + bytes, 0x0003); |
| 1128 bytes += qq_put8(raw_data + bytes, 0); |
1145 bytes += qq_put8(raw_data + bytes, 0); |
| 1129 bytes += qq_put8(raw_data + bytes, 0x03); |
1146 bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[1]); |
| 1130 bytes += qq_put8(raw_data + bytes, 0); |
1147 bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[2]); |
| 1131 bytes += qq_put8(raw_data + bytes, qd->ld.pwd_2nd_md5[1]); |
1148 |
| 1132 bytes += qq_put8(raw_data + bytes, qd->ld.pwd_2nd_md5[2]); |
1149 qq_show_packet("Check password", raw_data, bytes); |
| 1133 |
|
| 1134 /* Encrypted by random key*/ |
1150 /* Encrypted by random key*/ |
| 1135 encrypted_len = qq_encrypt(encrypted, raw_data, QQ_LOGIN_DATA_LENGTH, qd->ld.random_key); |
1151 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); |
| 1136 |
1152 |
| 1137 buf = g_newa(guint8, MAX_PACKET_SIZE); |
1153 buf = g_newa(guint8, MAX_PACKET_SIZE); |
| 1138 memset(buf, 0, MAX_PACKET_SIZE); |
1154 memset(buf, 0, MAX_PACKET_SIZE); |
| 1139 bytes = 0; |
1155 bytes = 0; |
| 1140 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); |
1156 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH); |
| 1141 bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); |
1157 bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); |
| 1142 |
1158 |
| 1143 qd->send_seq++; |
1159 qd->send_seq++; |
| 1144 qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); |
1160 qq_send_cmd_encrypted(gc, QQ_CMD_CHECK_PWD, qd->send_seq, buf, bytes, TRUE); |
| 1145 } |
1161 } |
| 1146 |
1162 |
| 1147 void qq_request_login_2007(PurpleConnection *gc) |
1163 void qq_request_login_2007(PurpleConnection *gc) |
| 1148 { |
1164 { |
| 1149 qq_data *qd; |
1165 qq_data *qd; |
| 1182 |
1198 |
| 1183 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ |
1199 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ |
| 1184 |
1200 |
| 1185 /* Encrypted password and put in encrypted */ |
1201 /* Encrypted password and put in encrypted */ |
| 1186 bytes = 0; |
1202 bytes = 0; |
| 1187 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_2nd_md5, sizeof(qd->ld.pwd_2nd_md5)); |
1203 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); |
| 1188 bytes += qq_put16(raw_data + bytes, 0); |
1204 bytes += qq_put16(raw_data + bytes, 0); |
| 1189 bytes += qq_put16(raw_data + bytes, 0xffff); |
1205 bytes += qq_put16(raw_data + bytes, 0xffff); |
| 1190 |
1206 |
| 1191 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_4th_md5); |
1207 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); |
| 1192 |
1208 |
| 1193 /* create packet */ |
1209 /* create packet */ |
| 1194 bytes = 0; |
1210 bytes = 0; |
| 1195 bytes += qq_put16(raw_data + bytes, 0); |
1211 bytes += qq_put16(raw_data + bytes, 0); |
| 1196 /* password encrypted */ |
1212 /* password encrypted */ |
| 1197 bytes += qq_put16(raw_data + bytes, encrypted_len); |
1213 bytes += qq_put16(raw_data + bytes, encrypted_len); |
| 1198 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
1214 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
| 1199 /* put data which NULL string encrypted by key pwd_4th_md5 */ |
1215 /* put data which NULL string encrypted by key pwd_twice_md5 */ |
| 1200 encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_4th_md5); |
1216 encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5); |
| 1201 g_return_if_fail(encrypted_len == 16); |
1217 g_return_if_fail(encrypted_len == 16); |
| 1202 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
1218 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
| 1203 /* unknow fill */ |
1219 /* unknow fill */ |
| 1204 memset(raw_data + bytes, 0, 19); |
1220 memset(raw_data + bytes, 0, 19); |
| 1205 bytes += 19; |
1221 bytes += 19; |
| 1335 |
1351 |
| 1336 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ |
1352 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ |
| 1337 |
1353 |
| 1338 /* Encrypted password and put in encrypted */ |
1354 /* Encrypted password and put in encrypted */ |
| 1339 bytes = 0; |
1355 bytes = 0; |
| 1340 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_2nd_md5, sizeof(qd->ld.pwd_2nd_md5)); |
1356 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); |
| 1341 bytes += qq_put16(raw_data + bytes, 0); |
1357 bytes += qq_put16(raw_data + bytes, 0); |
| 1342 bytes += qq_put16(raw_data + bytes, 0xffff); |
1358 bytes += qq_put16(raw_data + bytes, 0xffff); |
| 1343 |
1359 |
| 1344 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_4th_md5); |
1360 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); |
| 1345 |
1361 |
| 1346 /* create packet */ |
1362 /* create packet */ |
| 1347 bytes = 0; |
1363 bytes = 0; |
| 1348 bytes += qq_put16(raw_data + bytes, 0); /* Unknow */ |
1364 bytes += qq_put16(raw_data + bytes, 0); /* Unknow */ |
| 1349 bytes += qq_put8(raw_data + bytes, 0); /* Separator */ |
1365 bytes += qq_put8(raw_data + bytes, 0); /* Separator */ |
| 1350 /* password encrypted */ |
1366 /* password encrypted */ |
| 1351 bytes += qq_put16(raw_data + bytes, encrypted_len); |
1367 bytes += qq_put16(raw_data + bytes, encrypted_len); |
| 1352 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
1368 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
| 1353 /* put data which NULL string encrypted by key pwd_4th_md5 */ |
1369 /* put data which NULL string encrypted by key pwd_twice_md5 */ |
| 1354 encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_4th_md5); |
1370 encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5); |
| 1355 g_return_if_fail(encrypted_len == 16); |
1371 g_return_if_fail(encrypted_len == 16); |
| 1356 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
1372 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
| 1357 /* unknow 19 bytes zero filled*/ |
1373 /* unknow 19 bytes zero filled*/ |
| 1358 memset(raw_data + bytes, 0, 19); |
1374 memset(raw_data + bytes, 0, 19); |
| 1359 bytes += 19; |
1375 bytes += 19; |