| 57 } |
57 } |
| 58 |
58 |
| 59 /* process login reply which says OK */ |
59 /* process login reply which says OK */ |
| 60 static gint8 process_login_ok(PurpleConnection *gc, guint8 *data, gint len) |
60 static gint8 process_login_ok(PurpleConnection *gc, guint8 *data, gint len) |
| 61 { |
61 { |
| |
62 qq_data *qd; |
| 62 gint bytes; |
63 gint bytes; |
| 63 qq_data *qd; |
64 |
| 64 |
65 guint8 ret; |
| 65 struct { |
66 guint32 uid; |
| 66 guint8 result; |
67 struct in_addr ip; |
| 67 guint8 session_key[QQ_KEY_LENGTH]; |
68 guint16 port; |
| 68 guint32 uid; |
69 struct tm *tm_local; |
| 69 struct in_addr client_ip; /* those detected by server */ |
70 |
| 70 guint16 client_port; |
71 qd = (qq_data *) gc->proto_data; |
| 71 struct in_addr server_ip; |
72 qq_show_packet("Login reply", data, len); |
| 72 guint16 server_port; |
73 |
| 73 time_t login_time; |
|
| 74 guint8 unknown1[26]; |
|
| 75 struct in_addr unknown_server1_ip; |
|
| 76 guint16 unknown_server1_port; |
|
| 77 struct in_addr unknown_server2_ip; |
|
| 78 guint16 unknown_server2_port; |
|
| 79 guint16 unknown2; /* 0x0001 */ |
|
| 80 guint16 unknown3; /* 0x0000 */ |
|
| 81 guint8 unknown4[32]; |
|
| 82 guint8 unknown5[12]; |
|
| 83 struct in_addr last_client_ip; |
|
| 84 time_t last_login_time; |
|
| 85 guint8 unknown6[8]; |
|
| 86 } packet; |
|
| 87 |
|
| 88 qd = (qq_data *) gc->proto_data; |
|
| 89 /* FIXME, check QQ_LOGIN_REPLY_OK_PACKET_LEN here */ |
74 /* FIXME, check QQ_LOGIN_REPLY_OK_PACKET_LEN here */ |
| 90 bytes = 0; |
75 bytes = 0; |
| 91 |
76 bytes += qq_get8(&ret, data + bytes); |
| 92 /* 000-000: reply code */ |
77 bytes += qq_getdata(qd->session_key, sizeof(qd->session_key), data + bytes); |
| 93 bytes += qq_get8(&packet.result, data + bytes); |
78 get_session_md5(qd->session_md5, qd->uid, qd->session_key); |
| 94 /* 001-016: session key */ |
|
| 95 bytes += qq_getdata(packet.session_key, sizeof(packet.session_key), data + bytes); |
|
| 96 purple_debug_info("QQ", "Got session_key\n"); |
79 purple_debug_info("QQ", "Got session_key\n"); |
| 97 /* 017-020: login uid */ |
80 bytes += qq_get32(&uid, data + bytes); |
| 98 bytes += qq_get32(&packet.uid, data + bytes); |
81 if (uid != qd->uid) { |
| 99 /* 021-024: server detected user public IP */ |
82 purple_debug_warning("QQ", "My uid in login reply is %d, not %d\n", uid, qd->uid); |
| 100 bytes += qq_getIP(&packet.client_ip, data + bytes); |
83 } |
| 101 /* 025-026: server detected user port */ |
84 bytes += qq_getIP(&qd->my_ip, data + bytes); |
| 102 bytes += qq_get16(&packet.client_port, data + bytes); |
85 bytes += qq_get16(&qd->my_port, data + bytes); |
| 103 /* 027-030: server detected itself ip 127.0.0.1 ? */ |
86 purple_debug_info("QQ", "Internet IP: %s, %d\n", inet_ntoa(qd->my_ip), qd->my_port); |
| 104 bytes += qq_getIP(&packet.server_ip, data + bytes); |
87 |
| 105 /* 031-032: server listening port */ |
88 bytes += qq_getIP(&qd->my_local_ip, data + bytes); |
| 106 bytes += qq_get16(&packet.server_port, data + bytes); |
89 bytes += qq_get16(&qd->my_local_port, data + bytes); |
| 107 /* 033-036: login time for current session */ |
90 purple_debug_info("QQ", "Local IP: %s, %d\n", inet_ntoa(qd->my_local_ip), qd->my_local_port); |
| 108 bytes += qq_getime(&packet.login_time, data + bytes); |
91 |
| 109 /* 037-062: 26 bytes, unknown */ |
92 bytes += qq_getime(&qd->login_time, data + bytes); |
| 110 bytes += qq_getdata((guint8 *) &packet.unknown1, 26, data + bytes); |
93 tm_local = localtime(&qd->login_time); |
| 111 /* 063-066: unknown server1 ip address */ |
94 purple_debug_info("QQ", "Login time: %d-%d-%d, %d:%d:%d\n", |
| 112 bytes += qq_getIP(&packet.unknown_server1_ip, data + bytes); |
95 (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, |
| 113 /* 067-068: unknown server1 port */ |
96 tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); |
| 114 bytes += qq_get16(&packet.unknown_server1_port, data + bytes); |
97 /* skip unknown 2 bytes, 0x(03 0a) */ |
| 115 /* 069-072: unknown server2 ip address */ |
98 bytes += 2; |
| 116 bytes += qq_getIP(&packet.unknown_server2_ip, data + bytes); |
99 /* skip unknown 24 bytes, maybe token to access Qun shared files */ |
| 117 /* 073-074: unknown server2 port */ |
100 bytes += 24; |
| 118 bytes += qq_get16(&packet.unknown_server2_port, data + bytes); |
101 /* unknow ip and port */ |
| 119 /* 075-076: 2 bytes unknown */ |
102 bytes += qq_getIP(&ip, data + bytes); |
| 120 bytes += qq_get16(&packet.unknown2, data + bytes); |
103 bytes += qq_get16(&port, data + bytes); |
| 121 /* 077-078: 2 bytes unknown */ |
104 purple_debug_info("QQ", "Unknow IP: %s, %d\n", inet_ntoa(ip), port); |
| 122 bytes += qq_get16(&packet.unknown3, data + bytes); |
105 /* unknow ip and port */ |
| 123 /* 079-110: 32 bytes unknown */ |
106 bytes += qq_getIP(&ip, data + bytes); |
| 124 bytes += qq_getdata((guint8 *) &packet.unknown4, 32, data + bytes); |
107 bytes += qq_get16(&port, data + bytes); |
| 125 /* 111-122: 12 bytes unknown */ |
108 purple_debug_info("QQ", "Unknow IP: %s, %d\n", inet_ntoa(ip), port); |
| 126 bytes += qq_getdata((guint8 *) &packet.unknown5, 12, data + bytes); |
109 /* unknown 4 bytes, 0x(00 81 00 00)*/ |
| 127 /* 123-126: login IP of last session */ |
110 bytes += 4; |
| 128 bytes += qq_getIP(&packet.last_client_ip, data + bytes); |
111 /* skip unknown 32 bytes, maybe key to access QQ Home */ |
| 129 /* 127-130: login time of last session */ |
112 bytes += 32; |
| 130 bytes += qq_getime(&packet.last_login_time, data + bytes); |
113 /* skip unknown 16 bytes, 0x(00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00) */ |
| 131 /* 131-138: 8 bytes unknown */ |
114 bytes += 16; |
| 132 bytes += qq_getdata((guint8 *) &packet.unknown6, 8, data + bytes); |
115 /* time */ |
| |
116 bytes += qq_getime(&qd->last_login_time[0], data + bytes); |
| |
117 tm_local = localtime(&qd->last_login_time[0]); |
| |
118 purple_debug_info("QQ", "Last login time: %d-%d-%d, %d:%d:%d\n", |
| |
119 (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, |
| |
120 tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); |
| |
121 /* unknow time */ |
| |
122 g_return_val_if_fail(sizeof(qd->last_login_time) / sizeof(time_t) > 1, QQ_LOGIN_REPLY_OK); |
| |
123 bytes += qq_getime(&qd->last_login_time[1], data + bytes); |
| |
124 tm_local = localtime(&qd->last_login_time[1]); |
| |
125 purple_debug_info("QQ", "Time: %d-%d-%d, %d:%d:%d\n", |
| |
126 (1900 +tm_local->tm_year), (1 + tm_local->tm_mon), tm_local->tm_mday, |
| |
127 tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec); |
| |
128 |
| |
129 g_return_val_if_fail(sizeof(qd->last_login_time) / sizeof(time_t) > 2, QQ_LOGIN_REPLY_OK); |
| |
130 bytes += qq_getime(&qd->last_login_time[2], data + bytes); |
| |
131 tm_local = localtime(&qd->last_login_time[2]); |
| |
132 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, |
| |
134 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) */ |
| 133 |
136 |
| 134 if (bytes != QQ_LOGIN_REPLY_OK_PACKET_LEN) { /* fail parsing login info */ |
137 if (bytes != QQ_LOGIN_REPLY_OK_PACKET_LEN) { /* fail parsing login info */ |
| 135 purple_debug_warning("QQ", |
138 purple_debug_warning("QQ", |
| 136 "Fail parsing login info, expect %d bytes, read %d bytes\n", |
139 "Fail parsing login info, expect %d bytes, read %d bytes\n", |
| 137 QQ_LOGIN_REPLY_OK_PACKET_LEN, bytes); |
140 QQ_LOGIN_REPLY_OK_PACKET_LEN, bytes); |
| 138 } /* but we still go on as login OK */ |
141 } /* but we still go on as login OK */ |
| 139 |
|
| 140 memcpy(qd->session_key, packet.session_key, sizeof(qd->session_key)); |
|
| 141 get_session_md5(qd->session_md5, qd->uid, qd->session_key); |
|
| 142 |
|
| 143 qd->my_ip.s_addr = packet.client_ip.s_addr; |
|
| 144 |
|
| 145 qd->my_port = packet.client_port; |
|
| 146 qd->login_time = packet.login_time; |
|
| 147 qd->last_login_time = packet.last_login_time; |
|
| 148 qd->last_login_ip = g_strdup( inet_ntoa(packet.last_client_ip) ); |
|
| 149 |
|
| 150 return QQ_LOGIN_REPLY_OK; |
142 return QQ_LOGIN_REPLY_OK; |
| 151 } |
143 } |
| 152 |
144 |
| 153 /* process login reply packet which includes redirected new server address */ |
145 /* process login reply packet which includes redirected new server address */ |
| 154 static gint8 process_login_redirect(PurpleConnection *gc, guint8 *data, gint len) |
146 static gint8 process_login_redirect(PurpleConnection *gc, guint8 *data, gint len) |
| 1144 |
1142 |
| 1145 qd->send_seq++; |
1143 qd->send_seq++; |
| 1146 qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); |
1144 qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); |
| 1147 } |
1145 } |
| 1148 |
1146 |
| 1149 /* |
1147 void qq_request_login_2007(PurpleConnection *gc) |
| 1150 static void qq_send_packet_login2007(PurpleConnection *gc) |
1148 { |
| 1151 { |
1149 qq_data *qd; |
| 1152 qq_data *qd; |
1150 guint8 *buf, *raw_data; |
| 1153 guint8 *buf, *cursor, *cursor_verify_data; |
1151 gint bytes; |
| 1154 guint16 seq_ret; |
1152 guint8 *encrypted; |
| 1155 gint encrypted_len, bytes; |
1153 gint encrypted_len; |
| 1156 gint pos, bodyOffset, encrypted_data_bytes, tail_offset, body_length, temp_pos; |
1154 static const guint8 login_1_16[] = { |
| 1157 guint8 verifyData[QQ_LOGIN_DATA_LENGTH], raw_data[QQ_LOGIN_ENCRYPT_BUFFER], encrypted_data[QQ_LOGIN_DATA_LENGTH]; |
1155 0x56, 0x4E, 0xC8, 0xFB, 0x0A, 0x4F, 0xEF, 0xB3, |
| 1158 |
1156 0x7A, 0x5D, 0xD8, 0x86, 0x0F, 0xAC, 0xE5, 0x1A |
| 1159 memset(raw_data, 0, QQ_LOGIN_ENCRYPT_BUFFER); |
1157 }; |
| 1160 memset(verifyData, 0, QQ_LOGIN_DATA_LENGTH); |
1158 static const guint8 login_2_16[] = { |
| 1161 memset(encrypted_data, 0, QQ_LOGIN_DATA_LENGTH); |
1159 0x5E, 0x22, 0x3A, 0xBE, 0x13, 0xBF, 0xDA, 0x4C, |
| 1162 qd = (qq_data *) gc->proto_data; |
1160 0xA9, 0xB7, 0x0B, 0x43, 0x63, 0x51, 0x8E, 0x28 |
| |
1161 }; |
| |
1162 static const guint8 login_3_83[] = { |
| |
1163 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, |
| |
1164 0x00, 0x00, 0x01, 0x40, 0x01, 0x01, 0x58, 0x83, |
| |
1165 0xD0, 0x00, 0x10, 0x9D, 0x14, 0x64, 0x0A, 0x2E, |
| |
1166 0xE2, 0x11, 0xF7, 0x90, 0xF0, 0xB5, 0x5F, 0x16, |
| |
1167 0xFB, 0x41, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, |
| |
1168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| |
1169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| |
1170 0x00, 0x00, 0x00, 0x00, 0x02, 0x76, 0x3C, 0xEE, |
| |
1171 0x4A, 0x00, 0x10, 0x86, 0x81, 0xAD, 0x1F, 0xC8, |
| |
1172 0xC9, 0xCC, 0xCF, 0xCA, 0x9F, 0xFF, 0x88, 0xC0, |
| |
1173 0x5C, 0x88, 0xD5 |
| |
1174 }; |
| |
1175 g_return_if_fail(gc != NULL && gc->proto_data != NULL); |
| |
1176 qd = (qq_data *) gc->proto_data; |
| |
1177 |
| |
1178 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); |
| |
1179 |
| |
1180 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16); |
| |
1181 memset(raw_data, 0, MAX_PACKET_SIZE - 16); |
| |
1182 |
| |
1183 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ |
| |
1184 |
| |
1185 /* Encrypted password and put in encrypted */ |
| |
1186 bytes = 0; |
| |
1187 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_2nd_md5, sizeof(qd->ld.pwd_2nd_md5)); |
| |
1188 bytes += qq_put16(raw_data + bytes, 0); |
| |
1189 bytes += qq_put16(raw_data + bytes, 0xffff); |
| |
1190 |
| |
1191 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_4th_md5); |
| |
1192 |
| |
1193 /* create packet */ |
| |
1194 bytes = 0; |
| |
1195 bytes += qq_put16(raw_data + bytes, 0); |
| |
1196 /* password encrypted */ |
| |
1197 bytes += qq_put16(raw_data + bytes, encrypted_len); |
| |
1198 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
| |
1199 /* put data which NULL string encrypted by key pwd_4th_md5 */ |
| |
1200 encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_4th_md5); |
| |
1201 g_return_if_fail(encrypted_len == 16); |
| |
1202 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
| |
1203 /* unknow fill */ |
| |
1204 memset(raw_data + bytes, 0, 19); |
| |
1205 bytes += 19; |
| |
1206 bytes += qq_putdata(raw_data + bytes, login_1_16, sizeof(login_1_16)); |
| |
1207 |
| |
1208 bytes += qq_put8(raw_data + bytes, (guint8)rand() & 0xff); |
| |
1209 bytes += qq_put8(raw_data + bytes, qd->login_mode); |
| |
1210 /* unknow 10 bytes zero filled*/ |
| |
1211 memset(raw_data + bytes, 0, 10); |
| |
1212 bytes += 10; |
| |
1213 /* redirect data, 15 bytes */ |
| |
1214 bytes += qq_putdata(raw_data + bytes, (guint8 *)&qd->redirect_data, sizeof(qd->redirect_data)); |
| |
1215 /* unknow fill */ |
| |
1216 bytes += qq_putdata(raw_data + bytes, login_2_16, sizeof(login_2_16)); |
| |
1217 /* captcha token get from qq_process_token_ex */ |
| |
1218 bytes += qq_put8(raw_data + bytes, qd->captcha.token_len); |
| |
1219 bytes += qq_putdata(raw_data + bytes, qd->captcha.token, qd->captcha.token_len); |
| |
1220 /* unknow fill */ |
| |
1221 bytes += qq_putdata(raw_data + bytes, login_3_83, sizeof(login_3_83)); |
| |
1222 memset(raw_data + bytes, 0, 332 - sizeof(login_3_83)); |
| |
1223 bytes += 332 - sizeof(login_3_83); |
| |
1224 |
| |
1225 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.login_key); |
| |
1226 |
| 1163 buf = g_newa(guint8, MAX_PACKET_SIZE); |
1227 buf = g_newa(guint8, MAX_PACKET_SIZE); |
| 1164 |
1228 memset(buf, 0, MAX_PACKET_SIZE); |
| 1165 cursor = buf; |
1229 bytes = 0; |
| 1166 bytes = 0; |
1230 /* logint token get from qq_process_check_pwd_2007 */ |
| 1167 bytes += _create_packet_head_seq(buf, &cursor, gc, QQ_CMD_LOGIN, TRUE, &seq_ret); |
1231 bytes += qq_put16(buf + bytes, qd->ld.login_token_len); |
| 1168 bytes += create_packet_dw(buf, &cursor, qd->uid); |
1232 bytes += qq_putdata(buf + bytes, qd->ld.login_token, qd->ld.login_token_len); |
| 1169 |
1233 bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); |
| 1170 bodyOffset = bytes; |
1234 |
| 1171 |
1235 qd->send_seq++; |
| 1172 bytes += create_packet_w(buf, &cursor, qd->passport_key_lenght); |
1236 qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); |
| 1173 bytes += create_packet_data(buf, &cursor, qd->passport_key, qd->passport_key_lenght); |
1237 } |
| 1174 bytes += create_packet_w(buf, &cursor, 0); |
1238 |
| 1175 pos = bytes; |
1239 /* process the login reply packet */ |
| 1176 bytes += 2; |
1240 guint8 qq_process_login_2007( PurpleConnection *gc, guint8 *data, gint data_len) |
| 1177 cursor += 2; |
1241 { |
| 1178 |
1242 qq_data *qd; |
| 1179 encrypted_data_bytes = 0; |
1243 gint bytes; |
| 1180 cursor_verify_data = verifyData; |
1244 guint8 ret; |
| 1181 encrypted_data_bytes += create_packet_data(verifyData, &cursor_verify_data, qd->pwkey, QQ_KEY_LENGTH); |
1245 gchar *error; |
| 1182 encrypted_data_bytes += create_packet_b(verifyData, &cursor_verify_data, 0); |
1246 guint32 uid; |
| 1183 encrypted_data_bytes += create_packet_b(verifyData, &cursor_verify_data, 0); |
1247 |
| 1184 encrypted_data_bytes += create_packet_b(verifyData, &cursor_verify_data, 255); |
1248 g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR); |
| 1185 encrypted_data_bytes += create_packet_b(verifyData, &cursor_verify_data, 255); |
1249 |
| 1186 // encrypted_data_bytes += create_packet_w(verifyData, &cursor_verify_data, 0); |
1250 qd = (qq_data *) gc->proto_data; |
| 1187 |
1251 |
| 1188 qq_encrypt(verifyData, encrypted_data_bytes, qd->pwkey_double, encrypted_data, &encrypted_len); |
1252 bytes = 0; |
| 1189 bytes += create_packet_data(buf, &cursor, encrypted_data, encrypted_len); |
1253 bytes += qq_get8(&ret, data + bytes); |
| 1190 |
1254 if (ret != 0) { |
| 1191 temp_pos = bytes; |
1255 qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, |
| 1192 bytes = pos; |
1256 ">>> [default] decrypt and dump"); |
| 1193 cursor = buf+bytes; |
1257 error = g_strdup_printf( |
| 1194 bytes += create_packet_w(buf, &cursor, encrypted_len); |
1258 _("Unknow reply code when login (0x%02X)"), |
| 1195 bytes = temp_pos; |
1259 ret ); |
| 1196 cursor = buf+bytes; |
1260 purple_connection_error_reason(gc, |
| 1197 |
1261 PURPLE_CONNECTION_ERROR_OTHER_ERROR, |
| 1198 qq_encrypt((guint8 *) "", 0, qd->pwkey_double, raw_data, &encrypted_len); |
1262 error); |
| 1199 bytes += create_packet_data(buf, &cursor, raw_data, encrypted_len); |
1263 g_free(error); |
| 1200 |
1264 return QQ_LOGIN_REPLY_ERR; |
| 1201 g_memmove(buf+bytes, kQQFixedContent1_35, 35); |
1265 } |
| 1202 bytes += 35; |
1266 |
| 1203 cursor = buf+bytes; |
1267 bytes += qq_getdata(qd->session_key, sizeof(qd->session_key), data + bytes); |
| 1204 |
1268 purple_debug_info("QQ", "Got session_key\n"); |
| 1205 bytes += create_packet_b(buf, &cursor, g_random_int_range (0,255)); |
1269 get_session_md5(qd->session_md5, qd->uid, qd->session_key); |
| 1206 bytes += create_packet_b(buf, &cursor, qd->login_mode); |
1270 |
| 1207 |
1271 bytes += qq_get32(&uid, data + bytes); |
| 1208 bytes += create_packet_dw(buf, &cursor, 0); |
1272 if (uid != qd->uid) { |
| 1209 bytes += create_packet_dw(buf, &cursor, 0); |
1273 purple_debug_warning("QQ", "My uid in login reply is %d, not %d\n", uid, qd->uid); |
| 1210 bytes += create_packet_w(buf, &cursor, 0); |
1274 } |
| 1211 |
1275 bytes += qq_getIP(&qd->my_ip, data + bytes); |
| 1212 bytes += create_packet_data(buf, &cursor, qd->selected_server, qd->selected_server_lenght); |
1276 bytes += qq_get16(&qd->my_port, data + bytes); |
| 1213 |
1277 bytes += qq_getIP(&qd->my_local_ip, data + bytes); |
| 1214 g_memmove(buf+bytes, kQQFixedContent2_16, 16); |
1278 bytes += qq_get16(&qd->my_local_port, data + bytes); |
| 1215 bytes += 16; |
1279 bytes += qq_getime(&qd->login_time, data + bytes); |
| 1216 cursor = buf+bytes; |
1280 /* skip unknow 50 byte */ |
| 1217 |
1281 bytes += 50; |
| 1218 bytes += create_packet_b(buf, &cursor, qd->login_token_lenght); |
1282 /* skip client key 32 byte */ |
| 1219 bytes += create_packet_data(buf, &cursor, qd->login_token, qd->login_token_lenght); |
1283 bytes += 32; |
| 1220 |
1284 /* skip unknow 12 byte */ |
| 1221 g_memmove(buf+bytes, kQQFixedContent3_332, 332); |
1285 bytes += 12; |
| 1222 bytes += 332; |
1286 /* last login */ |
| 1223 cursor = buf+bytes; |
1287 bytes += qq_getIP(&qd->last_login_ip, data + bytes); |
| 1224 |
1288 bytes += qq_getime(&qd->last_login_time[0], data + bytes); |
| 1225 tail_offset = bytes; |
1289 purple_debug_info("QQ", "Last Login: %s, %s\n", |
| 1226 body_length = tail_offset - bodyOffset; |
1290 inet_ntoa(qd->last_login_ip), ctime(&qd->last_login_time[0])); |
| 1227 |
1291 return QQ_LOGIN_REPLY_OK; |
| 1228 memset(raw_data, 0, QQ_LOGIN_ENCRYPT_BUFFER); |
|
| 1229 encrypted_len = body_length; |
|
| 1230 // qq_encrypt(buf+passport_length+2+11, body_length-passport_length-2 , qd->pwkey, raw_data, &encrypted_len); |
|
| 1231 qq_encrypt(buf+qd->passport_key_lenght+2+11, body_length-qd->passport_key_lenght-2 , qd->login_key, raw_data, &encrypted_len); |
|
| 1232 bytes = qd->passport_key_lenght+2+11; |
|
| 1233 cursor = buf+bytes; |
|
| 1234 bytes += create_packet_data(buf, &cursor, raw_data, encrypted_len); |
|
| 1235 bytes += create_packet_b(buf, &cursor, QQ_PACKET_TAIL); |
|
| 1236 |
|
| 1237 if (bytes == (cursor - buf)) // packet creation OK |
|
| 1238 _qq_send_packet(gc, buf, bytes, QQ_CMD_LOGIN); |
|
| 1239 else |
|
| 1240 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Fail create login packet\n"); |
|
| 1241 |
|
| 1242 } |
|
| 1243 */ |
|
| 1244 void qq_request_login_2007(PurpleConnection *gc) |
|
| 1245 { |
|
| 1246 } |
1292 } |
| 1247 |
1293 |
| 1248 void qq_request_login_2008(PurpleConnection *gc) |
1294 void qq_request_login_2008(PurpleConnection *gc) |
| 1249 { |
1295 { |
| 1250 } |
1296 qq_data *qd; |
| |
1297 guint8 *buf, *raw_data; |
| |
1298 gint bytes; |
| |
1299 guint8 *encrypted; |
| |
1300 gint encrypted_len; |
| |
1301 guint8 index, count; |
| |
1302 |
| |
1303 static const guint8 login_1_16[] = { |
| |
1304 0xD2, 0x41, 0x75, 0x12, 0xC2, 0x86, 0x57, 0x10, |
| |
1305 0x78, 0x57, 0xDC, 0x24, 0x8C, 0xAA, 0x8F, 0x4E |
| |
1306 }; |
| |
1307 |
| |
1308 static const guint8 login_2_16[] = { |
| |
1309 0x94, 0x0B, 0x73, 0x7A, 0xA2, 0x51, 0xF0, 0x4B, |
| |
1310 0x95, 0x2F, 0xC6, 0x0A, 0x5B, 0xF6, 0x76, 0x52 |
| |
1311 }; |
| |
1312 static const guint8 login_3_18[] = { |
| |
1313 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, |
| |
1314 0x00, 0x00, 0x01, 0x40, 0x01, 0x1b, 0x02, 0x84, |
| |
1315 0x50, 0x00 |
| |
1316 }; |
| |
1317 static const guint8 login_4_16[] = { |
| |
1318 0x2D, 0x49, 0x15, 0x55, 0x78, 0xFC, 0xF3, 0xD4, |
| |
1319 0x53, 0x55, 0x60, 0x9C, 0x37, 0x9F, 0xE9, 0x59 |
| |
1320 }; |
| |
1321 static const guint8 login_5_6[] = { |
| |
1322 0x02, 0x68, 0xe8, 0x07, 0x83, 0x00 |
| |
1323 }; |
| |
1324 static const guint8 login_6_16[] = { |
| |
1325 0x3B, 0xCE, 0x43, 0xF1, 0x8B, 0xA4, 0x2B, 0xB5, |
| |
1326 0xB3, 0x51, 0x57, 0xF7, 0x06, 0x4B, 0x18, 0xFC |
| |
1327 }; |
| |
1328 g_return_if_fail(gc != NULL && gc->proto_data != NULL); |
| |
1329 qd = (qq_data *) gc->proto_data; |
| |
1330 |
| |
1331 g_return_if_fail(qd->ld.token != NULL && qd->ld.token_len > 0); |
| |
1332 |
| |
1333 raw_data = g_newa(guint8, MAX_PACKET_SIZE - 16); |
| |
1334 memset(raw_data, 0, MAX_PACKET_SIZE - 16); |
| |
1335 |
| |
1336 encrypted = g_newa(guint8, MAX_PACKET_SIZE); /* 16 bytes more */ |
| |
1337 |
| |
1338 /* Encrypted password and put in encrypted */ |
| |
1339 bytes = 0; |
| |
1340 bytes += qq_putdata(raw_data + bytes, qd->ld.pwd_2nd_md5, sizeof(qd->ld.pwd_2nd_md5)); |
| |
1341 bytes += qq_put16(raw_data + bytes, 0); |
| |
1342 bytes += qq_put16(raw_data + bytes, 0xffff); |
| |
1343 |
| |
1344 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.pwd_4th_md5); |
| |
1345 |
| |
1346 /* create packet */ |
| |
1347 bytes = 0; |
| |
1348 bytes += qq_put16(raw_data + bytes, 0); /* Unknow */ |
| |
1349 bytes += qq_put8(raw_data + bytes, 0); /* Separator */ |
| |
1350 /* password encrypted */ |
| |
1351 bytes += qq_put16(raw_data + bytes, encrypted_len); |
| |
1352 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
| |
1353 /* put data which NULL string encrypted by key pwd_4th_md5 */ |
| |
1354 encrypted_len = qq_encrypt(encrypted, (guint8 *) "", 0, qd->ld.pwd_4th_md5); |
| |
1355 g_return_if_fail(encrypted_len == 16); |
| |
1356 bytes += qq_putdata(raw_data + bytes, encrypted, encrypted_len); |
| |
1357 /* unknow 19 bytes zero filled*/ |
| |
1358 memset(raw_data + bytes, 0, 19); |
| |
1359 bytes += 19; |
| |
1360 bytes += qq_putdata(raw_data + bytes, login_1_16, sizeof(login_1_16)); |
| |
1361 |
| |
1362 index = rand() % 3; /* can be set as 1 */ |
| |
1363 for( count = 0; count < encrypted_len; count++ ) |
| |
1364 index ^= encrypted[count]; |
| |
1365 for( count = 0; count < sizeof(login_1_16); count++ ) |
| |
1366 index ^= login_1_16[count]; |
| |
1367 bytes += qq_put8(raw_data + bytes, index); /* random in QQ 2007*/ |
| |
1368 |
| |
1369 bytes += qq_put8(raw_data + bytes, qd->login_mode); |
| |
1370 /* unknow 10 bytes zero filled*/ |
| |
1371 memset(raw_data + bytes, 0, 10); |
| |
1372 bytes += 10; |
| |
1373 /* redirect data, 15 bytes */ |
| |
1374 bytes += qq_putdata(raw_data + bytes, (guint8 *)&qd->redirect_data, sizeof(qd->redirect_data)); |
| |
1375 /* unknow fill */ |
| |
1376 bytes += qq_putdata(raw_data + bytes, login_2_16, sizeof(login_2_16)); |
| |
1377 /* captcha token get from qq_process_token_ex */ |
| |
1378 bytes += qq_put8(raw_data + bytes, qd->captcha.token_len); |
| |
1379 bytes += qq_putdata(raw_data + bytes, qd->captcha.token, qd->captcha.token_len); |
| |
1380 /* unknow fill */ |
| |
1381 bytes += qq_putdata(raw_data + bytes, login_3_18, sizeof(login_3_18)); |
| |
1382 bytes += qq_put8(raw_data + bytes , sizeof(login_4_16)); |
| |
1383 bytes += qq_putdata(raw_data + bytes, login_4_16, sizeof(login_4_16)); |
| |
1384 /* unknow 10 bytes zero filled*/ |
| |
1385 memset(raw_data + bytes, 0, 10); |
| |
1386 bytes += 10; |
| |
1387 /* redirect data, 15 bytes */ |
| |
1388 bytes += qq_putdata(raw_data + bytes, (guint8 *)&qd->redirect_data, sizeof(qd->redirect_data)); |
| |
1389 /* unknow fill */ |
| |
1390 bytes += qq_putdata(raw_data + bytes, login_5_6, sizeof(login_5_6)); |
| |
1391 bytes += qq_put8(raw_data + bytes , sizeof(login_6_16)); |
| |
1392 bytes += qq_putdata(raw_data + bytes, login_6_16, sizeof(login_6_16)); |
| |
1393 /* unknow 249 bytes zero filled*/ |
| |
1394 memset(raw_data + bytes, 0, 249); |
| |
1395 bytes += 249; |
| |
1396 |
| |
1397 encrypted_len = qq_encrypt(encrypted, raw_data, bytes, qd->ld.login_key); |
| |
1398 |
| |
1399 buf = g_newa(guint8, MAX_PACKET_SIZE); |
| |
1400 memset(buf, 0, MAX_PACKET_SIZE); |
| |
1401 bytes = 0; |
| |
1402 /* logint token get from qq_process_check_pwd_2007 */ |
| |
1403 bytes += qq_put16(buf + bytes, qd->ld.login_token_len); |
| |
1404 bytes += qq_putdata(buf + bytes, qd->ld.login_token, qd->ld.login_token_len); |
| |
1405 bytes += qq_putdata(buf + bytes, encrypted, encrypted_len); |
| |
1406 |
| |
1407 qd->send_seq++; |
| |
1408 qq_send_cmd_encrypted(gc, QQ_CMD_LOGIN, qd->send_seq, buf, bytes, TRUE); |
| |
1409 } |
| |
1410 |
| |
1411 guint8 qq_process_login_2008( PurpleConnection *gc, guint8 *data, gint data_len) |
| |
1412 { |
| |
1413 qq_data *qd; |
| |
1414 gint bytes; |
| |
1415 guint8 ret; |
| |
1416 gchar *error; |
| |
1417 guint32 uid; |
| |
1418 |
| |
1419 g_return_val_if_fail(data != NULL && data_len != 0, QQ_LOGIN_REPLY_ERR); |
| |
1420 |
| |
1421 qd = (qq_data *) gc->proto_data; |
| |
1422 |
| |
1423 bytes = 0; |
| |
1424 bytes += qq_get8(&ret, data + bytes); |
| |
1425 if (ret != 0) { |
| |
1426 qq_hex_dump(PURPLE_DEBUG_WARNING, "QQ", data, data_len, |
| |
1427 ">>> [default] decrypt and dump"); |
| |
1428 error = g_strdup_printf( |
| |
1429 _("Unknow reply code when login (0x%02X)"), |
| |
1430 ret ); |
| |
1431 purple_connection_error_reason(gc, |
| |
1432 PURPLE_CONNECTION_ERROR_OTHER_ERROR, |
| |
1433 error); |
| |
1434 g_free(error); |
| |
1435 return QQ_LOGIN_REPLY_ERR; |
| |
1436 } |
| |
1437 |
| |
1438 bytes += qq_getdata(qd->session_key, sizeof(qd->session_key), data + bytes); |
| |
1439 purple_debug_info("QQ", "Got session_key\n"); |
| |
1440 get_session_md5(qd->session_md5, qd->uid, qd->session_key); |
| |
1441 |
| |
1442 bytes += qq_get32(&uid, data + bytes); |
| |
1443 if (uid != qd->uid) { |
| |
1444 purple_debug_warning("QQ", "My uid in login reply is %d, not %d\n", uid, qd->uid); |
| |
1445 } |
| |
1446 bytes += qq_getIP(&qd->my_ip, data + bytes); |
| |
1447 bytes += qq_get16(&qd->my_port, data + bytes); |
| |
1448 bytes += qq_getIP(&qd->my_local_ip, data + bytes); |
| |
1449 bytes += qq_get16(&qd->my_local_port, data + bytes); |
| |
1450 bytes += qq_getime(&qd->login_time, data + bytes); |
| |
1451 /* skip 1 byte, always 0x03 */ |
| |
1452 /* skip 1 byte, login mode */ |
| |
1453 bytes = 131; |
| |
1454 bytes += qq_getIP(&qd->last_login_ip, data + bytes); |
| |
1455 bytes += qq_getime(&qd->last_login_time[0], data + bytes); |
| |
1456 purple_debug_info("QQ", "Last Login: %s, %s\n", |
| |
1457 inet_ntoa(qd->last_login_ip), ctime(&qd->last_login_time[0])); |
| |
1458 return QQ_LOGIN_REPLY_OK; |
| |
1459 } |