comparison libpurple/protocols/qq/qq_base.c @ 24139:832178d951ca

2008.09.30 - ccpaging <ccpaging(at)gmail.com> * Successfully login using 2007/2008 protocols
author SHiNE CsyFeK <csyfek@gmail.com>
date Wed, 22 Oct 2008 14:42:23 +0000
parents dc112387190f
children 619ac2303c46
comparison
equal deleted inserted replaced
24138:dc112387190f 24139:832178d951ca
507 gint encrypted_len; 507 gint encrypted_len;
508 508
509 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 509 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
510 qd = (qq_data *) gc->proto_data; 510 qd = (qq_data *) gc->proto_data;
511 511
512 raw_data = g_newa(guint8, sizeof(qd->redirect_data)); 512 raw_data = g_newa(guint8, 128);
513 memset(raw_data, 0, sizeof(qd->redirect_data)); 513 memset(raw_data, 0, 128);
514 514
515 encrypted = g_newa(guint8, sizeof(qd->redirect_data) + 16); /* 16 bytes more */ 515 encrypted = g_newa(guint8, 128 + 16); /* 16 bytes more */
516 516
517 bytes = 0; 517 bytes = 0;
518 bytes += qq_put16(raw_data + bytes, qd->redirect_data.ret); 518 if (qd->redirect == NULL) {
519 bytes += qq_put8(raw_data + bytes, qd->redirect_data.b1); 519 /* first packet to get server */
520 bytes += qq_put32(raw_data + bytes, qd->redirect_data.w1); 520 qd->redirect_len = 15;
521 bytes += qq_put32(raw_data + bytes, qd->redirect_data.w2); 521 qd->redirect = g_realloc(qd->redirect, qd->redirect_len);
522 bytes += qq_putIP(raw_data + bytes, &(qd->redirect_data.ip)); 522 memset(qd->redirect, 0, qd->redirect_len);
523 }
524 bytes += qq_putdata(raw_data + bytes, qd->redirect, qd->redirect_len);
523 525
524 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); 526 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key);
525 527
526 buf = g_newa(guint8, MAX_PACKET_SIZE); 528 buf = g_newa(guint8, MAX_PACKET_SIZE);
527 memset(buf, 0, MAX_PACKET_SIZE); 529 memset(buf, 0, MAX_PACKET_SIZE);
535 537
536 guint16 qq_process_get_server(PurpleConnection *gc, guint8 *data, gint data_len) 538 guint16 qq_process_get_server(PurpleConnection *gc, guint8 *data, gint data_len)
537 { 539 {
538 qq_data *qd; 540 qq_data *qd;
539 gint bytes; 541 gint bytes;
542 guint16 ret;
540 543
541 g_return_val_if_fail (gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR); 544 g_return_val_if_fail (gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR);
542 qd = (qq_data *) gc->proto_data; 545 qd = (qq_data *) gc->proto_data;
543 546
544 g_return_val_if_fail (data != NULL, QQ_LOGIN_REPLY_ERR); 547 g_return_val_if_fail (data != NULL, QQ_LOGIN_REPLY_ERR);
545 548
546 /* qq_show_packet("Get Server", data, data_len); */ 549 /* qq_show_packet("Get Server", data, data_len); */
547 bytes = 0; 550 bytes = 0;
548 bytes += qq_get16(&qd->redirect_data.ret, data + bytes); 551 bytes += qq_get16(&ret, data + bytes);
549 if (qd->redirect_data.ret == 0) { 552 if (ret == 0) {
550 memset(&qd->redirect_data, 0, sizeof(qd->redirect_data)); 553 /* Notice: do not clear redirect_data here. It will be used in login*/
551 qd->redirect_ip.s_addr = 0; 554 qd->redirect_ip.s_addr = 0;
552 return QQ_LOGIN_REPLY_OK; 555 return QQ_LOGIN_REPLY_OK;
553 } 556 }
554 557
555 if (data_len < 15) { 558 if (data_len < 15) {
557 PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR, 560 PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
558 _("Can not decrypt get server reply")); 561 _("Can not decrypt get server reply"));
559 return QQ_LOGIN_REPLY_ERR; 562 return QQ_LOGIN_REPLY_ERR;
560 } 563 }
561 564
562 bytes += qq_get8(&qd->redirect_data.b1, data + bytes); 565 qd->redirect_len = data_len;
563 bytes += qq_get32(&qd->redirect_data.w1, data + bytes); 566 qd->redirect = g_realloc(qd->redirect, qd->redirect_len);
564 bytes += qq_get32(&qd->redirect_data.w2, data + bytes); 567 qq_getdata(qd->redirect, qd->redirect_len, data);
565 bytes += qq_getIP(&qd->redirect_data.ip, data + bytes); 568 qq_show_packet("Redirect to", qd->redirect, qd->redirect_len);
566 purple_debug_info("QQ", "Get server %d-%d-%d%d, %s\n", 569
567 qd->redirect_data.ret, qd->redirect_data.b1, qd->redirect_data.w1, qd->redirect_data.w2, 570 qq_getIP(&qd->redirect_ip, data + 11);
568 inet_ntoa(qd->redirect_data.ip)); 571 purple_debug_info("QQ", "Get server %s\n", inet_ntoa(qd->redirect_ip));
569
570 g_memmove(&qd->redirect_ip, &qd->redirect_data.ip, sizeof(qd->redirect_ip));
571 return QQ_LOGIN_REPLY_REDIRECT; 572 return QQ_LOGIN_REPLY_REDIRECT;
572 } 573 }
573 574
574 void qq_request_token_ex(PurpleConnection *gc) 575 void qq_request_token_ex(PurpleConnection *gc)
575 { 576 {
807 bytes += qq_get8(&sub_cmd, data + bytes); /* 03: ok; 04: need verifying */ 808 bytes += qq_get8(&sub_cmd, data + bytes); /* 03: ok; 04: need verifying */
808 bytes += 2; /* 0x(00 05) */ 809 bytes += 2; /* 0x(00 05) */
809 bytes += qq_get8(&reply, data + bytes); 810 bytes += qq_get8(&reply, data + bytes);
810 811
811 bytes += qq_get16(&(qd->ld.token_ex_len), data + bytes); 812 bytes += qq_get16(&(qd->ld.token_ex_len), data + bytes);
812 if (qd->ld.token_ex != NULL) g_free(qd->ld.token_ex); 813 qd->ld.token_ex = g_realloc(qd->ld.token_ex, qd->ld.token_ex_len);
813 qd->ld.token_ex = g_new0(guint8, qd->ld.token_ex_len);
814 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);
815
816 if(reply != 1) 815 if(reply != 1)
817 { 816 {
818 purple_debug_info("QQ", "Captcha verified, result %d\n", reply); 817 purple_debug_info("QQ", "Captcha verified, result %d\n", reply);
819 return QQ_LOGIN_REPLY_OK; 818 return QQ_LOGIN_REPLY_OK;
820 } 819 }
875 crc = (crc >> 8) ^ crc32_table[(crc ^ *buf++) & 0xff]; 874 crc = (crc >> 8) ^ crc32_table[(crc ^ *buf++) & 0xff];
876 875
877 return crc ^ 0xffffffffL; 876 return crc ^ 0xffffffffL;
878 } 877 }
879 878
880 void qq_request_check_pwd_2007(PurpleConnection *gc) 879 void qq_request_check_pwd(PurpleConnection *gc)
881 { 880 {
882 qq_data *qd; 881 qq_data *qd;
883 guint8 *buf, *raw_data; 882 guint8 *buf, *raw_data;
884 gint bytes; 883 gint bytes;
885 guint8 *encrypted; 884 guint8 *encrypted;
886 gint encrypted_len; 885 gint encrypted_len;
887 gint count;
888 static guint8 header[] = { 886 static guint8 header[] = {
889 0x00, 0x5F, 0x00, 0x00, 0x08, 0x04, 0x01, 0xE0 887 0x00, 0x5F, 0x00, 0x00, 0x08, 0x04, 0x01, 0xE0
890 }; 888 };
889 static guint8 unknown[] = {
890 0xDB, 0xB9, 0xF3, 0x0B, 0xF9, 0x13, 0x87, 0xB2,
891 0xE6, 0x20, 0x43, 0xBE, 0x53, 0xCA, 0x65, 0x03
892 };
891 893
892 g_return_if_fail(gc != NULL && gc->proto_data != NULL); 894 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
893 qd = (qq_data *) gc->proto_data; 895 qd = (qq_data *) gc->proto_data;
894 896
895 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); 897 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0);
900 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ 902 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */
901 903
902 /* Encrypted password and put in encrypted */ 904 /* Encrypted password and put in encrypted */
903 bytes = 0; 905 bytes = 0;
904 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5)); 906 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5));
905 bytes += qq_put16(raw_data + bytes, rand() & 0); 907 bytes += qq_put16(raw_data + bytes, 0);
906 bytes += qq_put16(raw_data + bytes, rand() & 0xffff); 908 bytes += qq_put16(raw_data + bytes, rand() & 0xffff);
907 909
908 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); 910 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5);
911
909 /* create packet */ 912 /* create packet */
910 bytes = 0; 913 bytes = 0;
911 bytes += qq_putdata(raw_data + bytes, header, sizeof(header)); 914 bytes += qq_putdata(raw_data + bytes, header, sizeof(header));
912 /* token get from qq_process_token_ex */ 915 /* token get from qq_request_token_ex */
913 bytes += qq_put8(raw_data + bytes, qd->ld.token_ex_len); 916 bytes += qq_put8(raw_data + bytes, qd->ld.token_ex_len);
914 bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len); 917 bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len);
915 /* password encrypted */ 918 /* password encrypted */
916 bytes += qq_put16(raw_data + bytes, encrypted_len); 919 bytes += qq_put16(raw_data + bytes, encrypted_len);
917 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); 920 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len);
918 /* random data, 20 bytes */ 921 /* len of unknown + len of CRC32 */
919 bytes += qq_put16(raw_data + bytes, 0x0014); /* length of next segment*/ 922 bytes += qq_put16(raw_data + bytes, sizeof(unknown) + 4);
920 count = 0x14; 923 bytes += qq_putdata(raw_data + bytes, unknown, sizeof(unknown));
921 while (count--) bytes += qq_put8(raw_data + bytes, rand() & 0xff); 924 bytes += qq_put32(
925 raw_data + bytes, crc32(0xFFFFFFFF, unknown, sizeof(unknown)));
926
922 /* put length into first 2 bytes */ 927 /* put length into first 2 bytes */
923 qq_put16(raw_data, bytes - 2); 928 qq_put8(raw_data + 1, bytes - 2);
929
924 /* tail */ 930 /* tail */
925 bytes += qq_put8(raw_data + bytes, 0); /* length of next segment */ 931 bytes += qq_put16(raw_data + bytes, 0x0003);
926 bytes += qq_put8(raw_data + bytes, 0x03); /* length of next segment */
927 bytes += qq_put8(raw_data + bytes, 0); 932 bytes += qq_put8(raw_data + bytes, 0);
928 bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[1]); 933 bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[1]);
929 bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[2]); 934 bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[2]);
930 qq_show_packet("QQ", raw_data, bytes); 935
936 /* qq_show_packet("Check password", raw_data, bytes); */
931 /* Encrypted by random key*/ 937 /* Encrypted by random key*/
932 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key); 938 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key);
933 939
934 buf = g_newa(guint8, MAX_PACKET_SIZE); 940 buf = g_newa(guint8, MAX_PACKET_SIZE);
935 memset(buf, 0, MAX_PACKET_SIZE); 941 memset(buf, 0, MAX_PACKET_SIZE);
939 945
940 qd->send_seq++; 946 qd->send_seq++;
941 qq_send_cmd_encrypted(gc, QQ_CMD_CHECK_PWD, qd->send_seq, buf, bytes, TRUE); 947 qq_send_cmd_encrypted(gc, QQ_CMD_CHECK_PWD, qd->send_seq, buf, bytes, TRUE);
942 } 948 }
943 949
944 guint8 qq_process_check_pwd_2007( PurpleConnection *gc, guint8 *data, gint data_len) 950 guint8 qq_process_check_pwd( PurpleConnection *gc, guint8 *data, gint data_len)
945 { 951 {
946 qq_data *qd; 952 qq_data *qd;
947 int bytes; 953 int bytes;
948 guint8 ret; 954 guint8 ret;
949 guint16 unknown_len;
950 gchar *error = NULL; 955 gchar *error = NULL;
956 guint16 unknow_token_len;
951 gchar *msg, *msg_utf8; 957 gchar *msg, *msg_utf8;
952 guint16 msg_len; 958 guint16 msg_len;
953 PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; 959 PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
954 960
955 g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR); 961 g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR);
956 962
957 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR); 963 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR);
958 qd = (qq_data *) gc->proto_data; 964 qd = (qq_data *) gc->proto_data;
959 965
960 bytes = 2; // skip 2 bytes 966 /* qq_show_packet("Check password reply", data, data_len); */
967
968 bytes = 0;
969 bytes += qq_get16(&unknow_token_len, data + bytes); /* maybe total length */
961 bytes += qq_get8(&ret, data + bytes); 970 bytes += qq_get8(&ret, data + bytes);
962 bytes += 4; // skip 4 bytes 971 bytes += 4; /* 0x(00 00 6d b9) */
963 /* 2 unknow */ 972 /* unknow_token_len may 0 when not reply ok*/
964 bytes += qq_get16(&unknown_len, data + bytes); 973 bytes += qq_get16(&unknow_token_len, data + bytes); /* 0x0020 */
965 bytes += unknown_len; 974 bytes += unknow_token_len;
966 bytes += qq_get16(&unknown_len, data + bytes); 975 bytes += qq_get16(&unknow_token_len, data + bytes); /* 0x0020 */
967 bytes += unknown_len; 976 bytes += unknow_token_len;
968 if (ret == QQ_LOGIN_REPLY_OK) { 977
978 if (ret == 0) {
969 /* get login_token */ 979 /* get login_token */
970 bytes += qq_get16(&qd->ld.login_token_len, data + bytes); 980 bytes += qq_get16(&qd->ld.login_token_len, data + bytes);
971 if (qd->ld.login_token != NULL) g_free(qd->ld.login_token); 981 if (qd->ld.login_token != NULL) g_free(qd->ld.login_token);
972 qd->ld.login_token = g_new0(guint8, qd->ld.login_token_len); 982 qd->ld.login_token = g_new0(guint8, qd->ld.login_token_len);
973 bytes += qq_getdata(qd->ld.login_token, qd->ld.login_token_len, data + bytes); 983 bytes += qq_getdata(qd->ld.login_token, qd->ld.login_token_len, data + bytes);
984 qq_show_packet("Get login token", qd->ld.login_token, qd->ld.login_token_len);
974 /* get login_key */ 985 /* get login_key */
975 bytes += qq_getdata(qd->ld.login_key, sizeof(qd->ld.login_key), data + bytes); 986 bytes += qq_getdata(qd->ld.login_key, sizeof(qd->ld.login_key), data + bytes);
987 qq_show_packet("Get login key", qd->ld.login_key, sizeof(qd->ld.login_key));
976 return QQ_LOGIN_REPLY_OK; 988 return QQ_LOGIN_REPLY_OK;
977 } 989 }
978 990
979 switch (ret) 991 switch (ret)
980 { 992 {
981 case 0x34: /* invalid password, 2nd byte is 0xc6 */ 993 case 0x34: /* invalid password */
982 if (!purple_account_get_remember_password(gc->account)) { 994 if (!purple_account_get_remember_password(gc->account)) {
983 purple_account_set_password(gc->account, NULL); 995 purple_account_set_password(gc->account, NULL);
984 } 996 }
985 error = g_strdup(_("Error password")); 997 error = g_strdup(_("Error password"));
986 reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED; 998 reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
1001 _("Unknow reply code when checking password (0x%02X)"), 1013 _("Unknow reply code when checking password (0x%02X)"),
1002 ret ); 1014 ret );
1003 reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR; 1015 reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
1004 break; 1016 break;
1005 } 1017 }
1006 qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, 1018
1007 ">>> [default] decrypt and dump");
1008 bytes = 11;
1009 bytes += qq_get16(&msg_len, data + bytes); 1019 bytes += qq_get16(&msg_len, data + bytes);
1010 1020
1011 msg = g_strndup((gchar *)data + bytes, msg_len); 1021 msg = g_strndup((gchar *)data + bytes, msg_len);
1012 msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT); 1022 msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
1013 1023
1014 purple_debug_error("QQ", "%s:\n%s\n", error, msg_utf8); 1024 purple_debug_error("QQ", "%s: %s\n", error, msg_utf8);
1015 purple_connection_error_reason(gc, reason, msg_utf8); 1025 purple_connection_error_reason(gc, reason, msg_utf8);
1016 1026
1017 g_free(error); 1027 g_free(error);
1018 g_free(msg); 1028 g_free(msg);
1019 g_free(msg_utf8); 1029 g_free(msg_utf8);
1020 return QQ_LOGIN_REPLY_ERR; 1030 return QQ_LOGIN_REPLY_ERR;
1021 }
1022
1023 guint8 qq_process_check_pwd_2008( PurpleConnection *gc, guint8 *data, gint data_len)
1024 {
1025 qq_data *qd;
1026 int bytes;
1027 guint8 ret;
1028 gchar *error = NULL;
1029 gchar *msg, *msg_utf8;
1030 guint16 msg_len;
1031 PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
1032
1033 g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR);
1034
1035 g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, QQ_LOGIN_REPLY_ERR);
1036 qd = (qq_data *) gc->proto_data;
1037
1038 bytes = 1; // skip 1 bytes, always 0
1039 bytes += qq_get8(&ret, data + bytes);
1040 if (ret == 0x97) {
1041 /* get login_token */
1042 bytes += qq_get16(&qd->ld.login_token_len, data);
1043 if (qd->ld.login_token != NULL) g_free(qd->ld.login_token);
1044 qd->ld.login_token = g_new0(guint8, qd->ld.login_token_len);
1045 bytes += qq_getdata(qd->ld.login_token, qd->ld.login_token_len, data + bytes);
1046 /* get login_key */
1047 bytes += qq_getdata(qd->ld.login_key, sizeof(qd->ld.login_key), data + bytes);
1048 return QQ_LOGIN_REPLY_OK;
1049 }
1050
1051 switch (ret)
1052 {
1053 case 0xc6: /* invalid password */
1054 if (!purple_account_get_remember_password(gc->account)) {
1055 purple_account_set_password(gc->account, NULL);
1056 }
1057 error = g_strdup(_("Error password"));
1058 reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
1059 break;
1060 case 0x33: /* need activation */
1061 case 0x51: /* need activation */
1062 error = g_strdup(_("Need active"));
1063 reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
1064 break;
1065 case 0xBF: /* uid is not exist */
1066 error = g_strdup(_("invalid user name"));
1067 reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
1068 break;
1069 default:
1070 qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len,
1071 ">>> [default] decrypt and dump");
1072 error = g_strdup_printf(
1073 _("Unknow reply code when checking password (0x%02X)"),
1074 ret );
1075 reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
1076 break;
1077 }
1078
1079 bytes = 11;
1080 bytes += qq_get16(&msg_len, data + bytes);
1081
1082 msg = g_strndup((gchar *)data + bytes, msg_len);
1083 msg_utf8 = qq_to_utf8(msg, QQ_CHARSET_DEFAULT);
1084
1085 purple_debug_error("QQ", "%s: %s\n", error, msg_utf8);
1086 purple_connection_error_reason(gc, reason, msg_utf8);
1087
1088 g_free(error);
1089 g_free(msg);
1090 g_free(msg_utf8);
1091 return QQ_LOGIN_REPLY_ERR;
1092 }
1093
1094 void qq_request_check_pwd_2008(PurpleConnection *gc)
1095 {
1096 qq_data *qd;
1097 guint8 *buf, *raw_data;
1098 gint bytes;
1099 guint8 *encrypted;
1100 gint encrypted_len;
1101 static guint8 header[] = {
1102 0x00, 0x5F, 0x00, 0x00, 0x08, 0x04, 0x01, 0xE0
1103 };
1104 static guint8 unknown[] = {
1105 0xDB, 0xB9, 0xF3, 0x0B, 0xF9, 0x13, 0x87, 0xB2,
1106 0xE6, 0x20, 0x43, 0xBE, 0x53, 0xCA, 0x65, 0x03
1107 };
1108
1109 g_return_if_fail(gc != NULL && gc->proto_data != NULL);
1110 qd = (qq_data *) gc->proto_data;
1111
1112 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0);
1113
1114 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16);
1115 memset(raw_data, 0, MAX_PACKET_SIZE - 16);
1116
1117 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */
1118
1119 /* Encrypted password and put in encrypted */
1120 bytes = 0;
1121 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_md5, sizeof(qd->ld.pwd_md5));
1122 bytes += qq_put16(raw_data + bytes, 0);
1123 bytes += qq_put16(raw_data + bytes, rand() & 0xffff);
1124
1125 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5);
1126
1127 /* create packet */
1128 bytes = 0;
1129 bytes += qq_putdata(raw_data + bytes, header, sizeof(header));
1130 /* token get from qq_request_token_ex */
1131 bytes += qq_put8(raw_data + bytes, qd->ld.token_ex_len);
1132 bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len);
1133 /* password encrypted */
1134 bytes += qq_put16(raw_data + bytes, encrypted_len);
1135 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len);
1136 /* len of unknown + len of CRC32 */
1137 bytes += qq_put16(raw_data + bytes, sizeof(unknown) + 4);
1138 bytes += qq_putdata(raw_data + bytes, unknown, sizeof(unknown));
1139 bytes += qq_put32(
1140 raw_data + bytes, crc32(0xFFFFFFFF, unknown, sizeof(unknown)));
1141 /* put length into first 2 bytes */
1142 qq_put16(raw_data, bytes - 2);
1143 /* tail */
1144 bytes += qq_put16(raw_data + bytes, 0x0003);
1145 bytes += qq_put8(raw_data + bytes, 0);
1146 bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[1]);
1147 bytes += qq_put8(raw_data + bytes, qd->ld.pwd_md5[2]);
1148
1149 qq_show_packet("Check password", raw_data, bytes);
1150 /* Encrypted by random key*/
1151 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.random_key);
1152
1153 buf = g_newa(guint8, MAX_PACKET_SIZE);
1154 memset(buf, 0, MAX_PACKET_SIZE);
1155 bytes = 0;
1156 bytes += qq_putdata(buf + bytes, qd->ld.random_key, QQ_KEY_LENGTH);
1157 bytes += qq_putdata(buf + bytes, encrypted, encrypted_len);
1158
1159 qd->send_seq++;
1160 qq_send_cmd_encrypted(gc, QQ_CMD_CHECK_PWD, qd->send_seq, buf, bytes, TRUE);
1161 } 1031 }
1162 1032
1163 void qq_request_login_2007(PurpleConnection *gc) 1033 void qq_request_login_2007(PurpleConnection *gc)
1164 { 1034 {
1165 qq_data *qd; 1035 qq_data *qd;
1206 1076
1207 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); 1077 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5);
1208 1078
1209 /* create packet */ 1079 /* create packet */
1210 bytes = 0; 1080 bytes = 0;
1211 bytes += qq_put16(raw_data + bytes, 0); 1081 bytes += qq_put16(raw_data + bytes, 0); /* Unknow */
1212 /* password encrypted */ 1082 /* password encrypted */
1213 bytes += qq_put16(raw_data + bytes, encrypted_len); 1083 bytes += qq_put16(raw_data + bytes, encrypted_len);
1214 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); 1084 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len);
1215 /* put data which NULL string encrypted by key pwd_twice_md5 */ 1085 /* put data which NULL string encrypted by key pwd_twice_md5 */
1216 encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5); 1086 encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5);
1217 g_return_if_fail(encrypted_len == 16); 1087 g_return_if_fail(encrypted_len == 16);
1218 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); 1088 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len);
1219 /* unknow fill */ 1089 /* unknow fill 0 */
1220 memset(raw_data + bytes, 0, 19); 1090 memset(raw_data + bytes, 0, 19);
1221 bytes += 19; 1091 bytes += 19;
1222 bytes += qq_putdata(raw_data + bytes, login_1_16, sizeof(login_1_16)); 1092 bytes += qq_putdata(raw_data + bytes, login_1_16, sizeof(login_1_16));
1223 1093
1224 bytes += qq_put8(raw_data + bytes, (guint8)rand() & 0xff); 1094 bytes += qq_put8(raw_data + bytes, rand() & 0xff);
1225 bytes += qq_put8(raw_data + bytes, qd->login_mode); 1095 bytes += qq_put8(raw_data + bytes, qd->login_mode);
1226 /* unknow 10 bytes zero filled*/ 1096 /* unknow 10 bytes zero filled*/
1227 memset(raw_data + bytes, 0, 10); 1097 memset(raw_data + bytes, 0, 10);
1228 bytes += 10; 1098 bytes += 10;
1229 /* redirect data, 15 bytes */ 1099 /* redirect data, 15 bytes */
1230 bytes += qq_putdata(raw_data + bytes, (guint8 *)&qd->redirect_data, sizeof(qd->redirect_data)); 1100 bytes += qq_putdata(raw_data + bytes, qd->redirect, qd->redirect_len);
1231 /* unknow fill */ 1101 /* unknow fill */
1232 bytes += qq_putdata(raw_data + bytes, login_2_16, sizeof(login_2_16)); 1102 bytes += qq_putdata(raw_data + bytes, login_2_16, sizeof(login_2_16));
1233 /* captcha token get from qq_process_token_ex */ 1103 /* captcha token get from qq_process_token_ex */
1234 bytes += qq_put8(raw_data + bytes, qd->captcha.token_len); 1104 bytes += qq_put8(raw_data + bytes, qd->ld.token_ex_len);
1235 bytes += qq_putdata(raw_data + bytes, qd->captcha.token, qd->captcha.token_len); 1105 bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len);
1236 /* unknow fill */ 1106 /* unknow fill */
1237 bytes += qq_putdata(raw_data + bytes, login_3_83, sizeof(login_3_83)); 1107 bytes += qq_putdata(raw_data + bytes, login_3_83, sizeof(login_3_83));
1238 memset(raw_data + bytes, 0, 332 - sizeof(login_3_83)); 1108 memset(raw_data + bytes, 0, 332 - sizeof(login_3_83));
1239 bytes += 332 - sizeof(login_3_83); 1109 bytes += 332 - sizeof(login_3_83);
1110
1111 qq_show_packet("Login", raw_data, bytes);
1240 1112
1241 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.login_key); 1113 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.login_key);
1242 1114
1243 buf = g_newa(guint8, MAX_PACKET_SIZE); 1115 buf = g_newa(guint8, MAX_PACKET_SIZE);
1244 memset(buf, 0, MAX_PACKET_SIZE); 1116 memset(buf, 0, MAX_PACKET_SIZE);
1360 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5); 1232 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_twice_md5);
1361 1233
1362 /* create packet */ 1234 /* create packet */
1363 bytes = 0; 1235 bytes = 0;
1364 bytes += qq_put16(raw_data + bytes, 0); /* Unknow */ 1236 bytes += qq_put16(raw_data + bytes, 0); /* Unknow */
1365 bytes += qq_put8(raw_data + bytes, 0); /* Separator */
1366 /* password encrypted */ 1237 /* password encrypted */
1367 bytes += qq_put16(raw_data + bytes, encrypted_len); 1238 bytes += qq_put16(raw_data + bytes, encrypted_len);
1368 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); 1239 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len);
1369 /* put data which NULL string encrypted by key pwd_twice_md5 */ 1240 /* put data which NULL string encrypted by key pwd_twice_md5 */
1370 encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5); 1241 encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_twice_md5);
1385 bytes += qq_put8(raw_data + bytes, qd->login_mode); 1256 bytes += qq_put8(raw_data + bytes, qd->login_mode);
1386 /* unknow 10 bytes zero filled*/ 1257 /* unknow 10 bytes zero filled*/
1387 memset(raw_data + bytes, 0, 10); 1258 memset(raw_data + bytes, 0, 10);
1388 bytes += 10; 1259 bytes += 10;
1389 /* redirect data, 15 bytes */ 1260 /* redirect data, 15 bytes */
1390 bytes += qq_putdata(raw_data + bytes, (guint8 *)&qd->redirect_data, sizeof(qd->redirect_data)); 1261 bytes += qq_putdata(raw_data + bytes, qd->redirect, qd->redirect_len);
1391 /* unknow fill */ 1262 /* unknow fill */
1392 bytes += qq_putdata(raw_data + bytes, login_2_16, sizeof(login_2_16)); 1263 bytes += qq_putdata(raw_data + bytes, login_2_16, sizeof(login_2_16));
1393 /* captcha token get from qq_process_token_ex */ 1264 /* captcha token get from qq_process_token_ex */
1394 bytes += qq_put8(raw_data + bytes, qd->captcha.token_len); 1265 bytes += qq_put8(raw_data + bytes, qd->ld.token_ex_len);
1395 bytes += qq_putdata(raw_data + bytes, qd->captcha.token, qd->captcha.token_len); 1266 bytes += qq_putdata(raw_data + bytes, qd->ld.token_ex, qd->ld.token_ex_len);
1396 /* unknow fill */ 1267 /* unknow fill */
1397 bytes += qq_putdata(raw_data + bytes, login_3_18, sizeof(login_3_18)); 1268 bytes += qq_putdata(raw_data + bytes, login_3_18, sizeof(login_3_18));
1398 bytes += qq_put8(raw_data + bytes , sizeof(login_4_16)); 1269 bytes += qq_put8(raw_data + bytes , sizeof(login_4_16));
1399 bytes += qq_putdata(raw_data + bytes, login_4_16, sizeof(login_4_16)); 1270 bytes += qq_putdata(raw_data + bytes, login_4_16, sizeof(login_4_16));
1400 /* unknow 10 bytes zero filled*/ 1271 /* unknow 10 bytes zero filled*/
1401 memset(raw_data + bytes, 0, 10); 1272 memset(raw_data + bytes, 0, 10);
1402 bytes += 10; 1273 bytes += 10;
1403 /* redirect data, 15 bytes */ 1274 /* redirect data, 15 bytes */
1404 bytes += qq_putdata(raw_data + bytes, (guint8 *)&qd->redirect_data, sizeof(qd->redirect_data)); 1275 bytes += qq_putdata(raw_data + bytes, qd->redirect, qd->redirect_len);
1405 /* unknow fill */ 1276 /* unknow fill */
1406 bytes += qq_putdata(raw_data + bytes, login_5_6, sizeof(login_5_6)); 1277 bytes += qq_putdata(raw_data + bytes, login_5_6, sizeof(login_5_6));
1407 bytes += qq_put8(raw_data + bytes , sizeof(login_6_16)); 1278 bytes += qq_put8(raw_data + bytes , sizeof(login_6_16));
1408 bytes += qq_putdata(raw_data + bytes, login_6_16, sizeof(login_6_16)); 1279 bytes += qq_putdata(raw_data + bytes, login_6_16, sizeof(login_6_16));
1409 /* unknow 249 bytes zero filled*/ 1280 /* unknow 249 bytes zero filled*/
1410 memset(raw_data + bytes, 0, 249); 1281 memset(raw_data + bytes, 0, 249);
1411 bytes += 249; 1282 bytes += 249;
1412 1283
1284 qq_show_packet("Login request", raw_data, bytes);
1413 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.login_key); 1285 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.login_key);
1414 1286
1415 buf = g_newa(guint8, MAX_PACKET_SIZE); 1287 buf = g_newa(guint8, MAX_PACKET_SIZE);
1416 memset(buf, 0, MAX_PACKET_SIZE); 1288 memset(buf, 0, MAX_PACKET_SIZE);
1417 bytes = 0; 1289 bytes = 0;