Mercurial > pidgin
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; |