Пример #1
0
void qq_process_request_login_token_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
{
        qq_data *qd;
	gchar *hex_dump;

        g_return_if_fail(buf != NULL && buf_len != 0);

        qd = (qq_data *) gc->proto_data;

	if (buf[0] == QQ_REQUEST_LOGIN_TOKEN_REPLY_OK) {
		if (buf[1] != buf_len-2) {
			purple_debug(PURPLE_DEBUG_INFO, "QQ", 
					"Malformed login token reply packet. Packet specifies length of %d, actual length is %d\n", buf[1], buf_len-2);
			purple_debug(PURPLE_DEBUG_INFO, "QQ",
					"Attempting to proceed with the actual packet length.\n");
		}
		hex_dump = hex_dump_to_str(buf+2, buf_len-2);
		purple_debug(PURPLE_DEBUG_INFO, "QQ",
                                   "<<< got a token with %d bytes -> [default] decrypt and dump\n%s", buf_len-2, hex_dump);
		qq_send_packet_login(gc, buf_len-2, buf+2);
	} else {
		purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Unknown request login token reply code : %d\n", buf[0]);
		hex_dump = hex_dump_to_str(buf, buf_len);
                purple_debug(PURPLE_DEBUG_WARNING, "QQ",
           		           ">>> %d bytes -> [default] decrypt and dump\n%s",
	                           buf_len, hex_dump);
               		try_dump_as_gbk(buf, buf_len);
		purple_connection_error(gc, _("Error requesting login token"));
	}		
	g_free(hex_dump);
}
Пример #2
0
/* send a file to udp channel with QQ_FILE_CONTROL_PACKET_TAG */
void qq_send_file_ctl_packet(PurpleConnection *gc, guint16 packet_type, guint32 to_uid, guint8 hellobyte)
{
	qq_data *qd;
	gint bytes, bytes_expected, encrypted_len;
	guint8 *raw_data, *encrypted;
	time_t now;
	ft_info *info;

	qd = (qq_data *) gc->proto_data;
	info = (ft_info *) qd->xfer->data;

	raw_data = g_newa (guint8, 61);
	bytes = 0;

	now = time(NULL);

	bytes += qq_putdata(raw_data + bytes, qd->session_md5, 16);
	bytes += qq_put16(raw_data + bytes, packet_type);
	switch (packet_type) {
		case QQ_FILE_CMD_SENDER_SAY_HELLO:
		case QQ_FILE_CMD_SENDER_SAY_HELLO_ACK:
		case QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK:
		case QQ_FILE_CMD_NOTIFY_IP_ACK:
		case QQ_FILE_CMD_RECEIVER_SAY_HELLO:
			bytes += qq_put16(raw_data + bytes, info->send_seq);
			break;
		default:
			bytes += qq_put16(raw_data + bytes, ++qd->send_seq);
	}
	bytes += qq_put32(raw_data + bytes, (guint32) now);
	bytes += qq_put8(raw_data + bytes, 0x00);
	bytes += qq_put8(raw_data + bytes, qd->my_icon);
	bytes += qq_put32(raw_data + bytes, 0x00000000);
	bytes += qq_put32(raw_data + bytes, 0x00000000);
	bytes += qq_put32(raw_data + bytes, 0x00000000);
	bytes += qq_put32(raw_data + bytes, 0x00000000);
	bytes += qq_put16(raw_data + bytes, 0x0000);
	bytes += qq_put8(raw_data + bytes, 0x00);
	/* 0x65: send a file, 0x6b: send a custom face */
	bytes += qq_put8(raw_data + bytes, QQ_FILE_TRANSFER_FILE); /* FIXME temp by gfhuang */
	switch (packet_type)
	{
		case QQ_FILE_CMD_SENDER_SAY_HELLO:
		case QQ_FILE_CMD_RECEIVER_SAY_HELLO:
		case QQ_FILE_CMD_SENDER_SAY_HELLO_ACK:
		case QQ_FILE_CMD_RECEIVER_SAY_HELLO_ACK:
			bytes += qq_put8(raw_data + bytes, 0x00);
			bytes += qq_put8(raw_data + bytes, hellobyte);
			bytes_expected = 48;
			break;
		case QQ_FILE_CMD_PING:
		case QQ_FILE_CMD_PONG:
		case QQ_FILE_CMD_NOTIFY_IP_ACK:
			bytes += qq_fill_conn_info(raw_data, info);
			bytes_expected = 61;
			break;
		default:
			purple_debug_info("QQ", "qq_send_file_ctl_packet: Unknown packet type[%d]\n",
					packet_type);
			bytes_expected = 0;
	}

	if (bytes != bytes_expected) {
		purple_debug_error("QQ", "qq_send_file_ctl_packet: Expected to get %d bytes, but get %d\n",
				bytes_expected, bytes);
		return;
	}

	qq_hex_dump(PURPLE_DEBUG_INFO, "QQ",
		raw_data, bytes,
		"sending packet[%s]:", qq_get_file_cmd_desc(packet_type));

	encrypted = g_newa(guint8, bytes + 17);
	encrypted_len = qq_encrypt(encrypted, raw_data, bytes, info->file_session_key);
	/*debug: try to decrypt it */

#if 0
	guint8 *buf;
	int buflen;
	hex_dump = hex_dump_to_str(encrypted, encrypted_len);
	purple_debug_info("QQ", "encrypted packet: \n%s\n", hex_dump);
	g_free(hex_dump);
	buf = g_newa(guint8, MAX_PACKET_SIZE);
	buflen = encrypted_len;
	if (qq_crypt(DECRYPT, encrypted, encrypted_len, info->file_session_key, buf, &buflen)) {
		purple_debug_info("QQ", "decrypt success\n");
	   if (buflen == bytes && memcmp(raw_data, buf, buflen) == 0)
			purple_debug_info("QQ", "checksum ok\n");

		hex_dump = hex_dump_to_str(buf, buflen);
		purple_debug_info("QQ", "decrypted packet: \n%s\n", hex_dump);
		g_free(hex_dump);
	 } else {
		purple_debug_info("QQ", "decrypt fail\n");
	}
#endif

	purple_debug_info("QQ", "<== send %s packet\n", qq_get_file_cmd_desc(packet_type));
	_qq_send_file(gc, encrypted, encrypted_len, QQ_FILE_CONTROL_PACKET_TAG, info->to_uid);
}
Пример #3
0
/* process the login reply packet */
void qq_process_login_reply(guint8 *buf, gint buf_len, PurpleConnection *gc)
{
	gint len, ret, bytes;
	guint8 *data;
	qq_data *qd;
	gchar *hex_dump;

	g_return_if_fail(buf != NULL && buf_len != 0);

	qd = (qq_data *) gc->proto_data;
	len = buf_len;
	data = g_newa(guint8, len);

	if (qq_crypt(DECRYPT, buf, buf_len, qd->pwkey, data, &len)) {
		/* should be able to decrypt with pwkey */
		purple_debug(PURPLE_DEBUG_INFO, "QQ", "Decrypt login reply packet with pwkey, %d bytes\n", len);
		if (data[0] == QQ_LOGIN_REPLY_OK) {
			ret = _qq_process_login_ok(gc, data, len);
		} else {
			purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Unknown login reply code : %d\n", data[0]);
			ret = QQ_LOGIN_REPLY_MISC_ERROR;
		}
	} else {		/* decrypt with pwkey error */
		len = buf_len;	/* reset len, decrypt will fail if len is too short */
		if (qq_crypt(DECRYPT, buf, buf_len, qd->inikey, data, &len)) {
			/* decrypt ok with inipwd, it might be password error */
			purple_debug(PURPLE_DEBUG_WARNING, "QQ", 
					"Decrypt login reply packet with inikey, %d bytes\n", len);
			bytes = 0;
			switch (data[0]) {
			case QQ_LOGIN_REPLY_REDIRECT:
				ret = _qq_process_login_redirect(gc, data, len);
				break;
			case QQ_LOGIN_REPLY_PWD_ERROR:
				ret = _qq_process_login_wrong_pwd(gc, data, len);
				break;
			default:
				purple_debug(PURPLE_DEBUG_ERROR, "QQ", "Unknown reply code: %d\n", data[0]);
				hex_dump = hex_dump_to_str(data, len);
		                purple_debug(PURPLE_DEBUG_WARNING, "QQ",
                		           ">>> %d bytes -> [default] decrypt and dump\n%s",
		                           buf_len, hex_dump);
				g_free(hex_dump);
                		try_dump_as_gbk(data, len);

				ret = QQ_LOGIN_REPLY_MISC_ERROR;
			}
		} else {	/* no idea how to decrypt */
			purple_debug(PURPLE_DEBUG_ERROR, "QQ", "No idea how to decrypt login reply\n");
			ret = QQ_LOGIN_REPLY_MISC_ERROR;
		}
	}

	switch (ret) {
	case QQ_LOGIN_REPLY_PWD_ERROR:
		gc->wants_to_die = TRUE;
		purple_connection_error(gc, _("Incorrect password."));
		break;
	case QQ_LOGIN_REPLY_MISC_ERROR:
		purple_connection_error(gc, _("Unable to login, check debug log"));
		break;
	case QQ_LOGIN_REPLY_OK:
		purple_debug(PURPLE_DEBUG_INFO, "QQ", "Login replys OK, everything is fine\n");
		break;
	case QQ_LOGIN_REPLY_REDIRECT:
		/* the redirect has been done in _qq_process_login_reply */
		break;
	default:{;
		}
	}
}
Пример #4
0
/* recv an IM from a group chat */
void qq_process_recv_group_im(guint8 *data, guint8 **cursor, gint data_len, 
		guint32 internal_group_id, GaimConnection *gc, guint16 im_type)
{
	gchar *msg_with_gaim_smiley, *msg_utf8_encoded, *im_src_name, *hex_dump;
	guint16 unknown;
	guint32 unknown4;
	GaimConversation *conv;
	qq_data *qd;
	qq_buddy *member;
	qq_group *group;
	qq_recv_group_im *im_group;
	gint skip_len;

	g_return_if_fail(data != NULL && data_len > 0);
	qd = (qq_data *) gc->proto_data;

	hex_dump = hex_dump_to_str(*cursor, data_len - (*cursor - data));
	gaim_debug(GAIM_DEBUG_INFO, "QQ", "group im hex dump\n%s\n", hex_dump);

	if (*cursor >= (data + data_len - 1)) {
		gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Received group im_group is empty\n");
		return;
	}

	im_group = g_newa(qq_recv_group_im, 1);

	read_packet_dw(data, cursor, data_len, &(im_group->external_group_id));
	read_packet_b(data, cursor, data_len, &(im_group->group_type));

	if(QQ_RECV_IM_TEMP_QUN_IM == im_type) {
		read_packet_dw(data, cursor, data_len, &(internal_group_id));
	}

	read_packet_dw(data, cursor, data_len, &(im_group->member_uid));
	read_packet_w(data, cursor, data_len, &unknown);	/* 0x0001? */
	read_packet_w(data, cursor, data_len, &(im_group->msg_seq));
	read_packet_dw(data, cursor, data_len, (guint32 *) & (im_group->send_time));
	read_packet_dw(data, cursor, data_len, &unknown4);	/* versionID */
	/*
	 * length includes font_attr
	 * this msg_len includes msg and font_attr
	 **** the format is ****
	 * length of all
	 * 1. unknown 10 bytes
	 * 2. 0-ended string
	 * 3. font_attr
	 */

	read_packet_w(data, cursor, data_len, &(im_group->msg_len));
	g_return_if_fail(im_group->msg_len > 0);

	/*
	 * 10 bytes from lumaqq
	 *    contentType = buf.getChar();
	 *    totalFragments = buf.get() & 255;
	 *    fragmentSequence = buf.get() & 255;
	 *    messageId = buf.getChar();
	 *    buf.getInt();
	 */

	if(im_type != QQ_RECV_IM_UNKNOWN_QUN_IM)
		skip_len = 10;
	else
		skip_len = 0;
	*cursor += skip_len;

	im_group->msg = g_strdup((gchar *) *cursor);
	*cursor += strlen(im_group->msg) + 1;
	/* there might not be any font_attr, check it */
	im_group->font_attr_len = im_group->msg_len - strlen(im_group->msg) - 1 - skip_len;
	if (im_group->font_attr_len > 0)
		im_group->font_attr = g_memdup(*cursor, im_group->font_attr_len);
	else
		im_group->font_attr = NULL;

	/* group im_group has no flag to indicate whether it has font_attr or not */
	msg_with_gaim_smiley = qq_smiley_to_gaim(im_group->msg);
	if (im_group->font_attr_len > 0)
		msg_utf8_encoded = qq_encode_to_gaim(im_group->font_attr,
						     im_group->font_attr_len, msg_with_gaim_smiley);
	else
		msg_utf8_encoded = qq_to_utf8(msg_with_gaim_smiley, QQ_CHARSET_DEFAULT);

	group = qq_group_find_by_id(gc, internal_group_id, QQ_INTERNAL_ID);
	g_return_if_fail(group != NULL);

	conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, group->group_name_utf8, gaim_connection_get_account(gc));
	if (conv == NULL && gaim_prefs_get_bool("/plugins/prpl/qq/prompt_group_msg_on_recv")) {
		serv_got_joined_chat(gc, qd->channel++, group->group_name_utf8);
		conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_CHAT, group->group_name_utf8, gaim_connection_get_account(gc));
	}

	if (conv != NULL) {
		member = qq_group_find_member_by_uid(group, im_group->member_uid);
		if (member == NULL || member->nickname == NULL)
			im_src_name = uid_to_gaim_name(im_group->member_uid);
		else
			im_src_name = g_strdup(member->nickname);
		serv_got_chat_in(gc,
				 gaim_conv_chat_get_id(GAIM_CONV_CHAT
						       (conv)), im_src_name, 0, msg_utf8_encoded, im_group->send_time);
		g_free(im_src_name);
	}
	g_free(hex_dump);
	g_free(msg_with_gaim_smiley);
	g_free(msg_utf8_encoded);
	g_free(im_group->msg);
	g_free(im_group->font_attr);
}