Esempio n. 1
0
/**
 * aim_gettlv8 - Retrieve the Nth TLV in chain as a 8bit integer.
 * @list: Source TLV chain
 * @type: TLV type to search for
 * @nth: Index of TLV to return
 *
 * Same as aim_gettlv(), except that the return value is a 
 * 8bit integer instead of an aim_tlv_t. 
 *
 */
faim_internal fu8_t aim_gettlv8(aim_tlvlist_t *list, const fu16_t t, const int n)
{
	aim_tlv_t *tlv;

	if (!(tlv = aim_gettlv(list, t, n)))
		return 0; /* erm */
	return aimutil_get8(tlv->value);
}
Esempio n. 2
0
guint8 byte_stream_get8(ByteStream *bs)
{

	if (byte_stream_empty(bs) < 1)
		return 0; /* XXX throw an exception */

	bs->offset++;

	return aimutil_get8(bs->data + bs->offset - 1);
}
Esempio n. 3
0
faim_internal fu8_t aimbs_get8(aim_bstream_t *bs)
{

    if (aim_bstream_empty(bs) < 1)
        return 0; /* XXX throw an exception */

    bs->offset++;

    return aimutil_get8(bs->data + bs->offset - 1);
}
Esempio n. 4
0
guint8 aimbs_get8(aim_bstream_t *bs)
{

	if (aim_bstream_empty(bs) < 1) {
		return 0; /* XXX throw an exception */

	}
	bs->offset++;

	return aimutil_get8(bs->data + bs->offset - 1);
}
Esempio n. 5
0
/**
 * Read in all available data on the socket for a given connection.
 * All complete FLAPs handled immedate after they're received.
 * Incomplete FLAP data is stored locally and appended to the next
 * time this callback is triggered.
 *
 * This is called by flap_connection_recv_cb and
 * flap_connection_recv_cb_ssl for unencrypted/encrypted connections.
 */
static void
flap_connection_recv(FlapConnection *conn)
{
	gpointer buf;
	gsize buflen;
	gssize read;

	/* Read data until we run out of data and break out of the loop */
	while (TRUE)
	{
		/* Start reading a new FLAP */
		if (conn->buffer_incoming.data.data == NULL)
		{
			buf = conn->header + conn->header_received;
			buflen = 6 - conn->header_received;

			/* Read the first 6 bytes (the FLAP header) */
			if (conn->gsc)
				read = purple_ssl_read(conn->gsc, buf, buflen);
			else
				read = recv(conn->fd, buf, buflen, 0);

			/* Check if the FLAP server closed the connection */
			if (read == 0)
			{
				flap_connection_schedule_destroy(conn,
						OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
				break;
			}

			/* If there was an error then close the connection */
			if (read < 0)
			{
				if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
					/* No worries */
					break;

				/* Error! */
				flap_connection_schedule_destroy(conn,
						OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
				break;
			}
			conn->od->gc->last_received = time(NULL);

			/* If we don't even have a complete FLAP header then do nothing */
			conn->header_received += read;
			if (conn->header_received < 6)
				break;

			/* All FLAP frames must start with the byte 0x2a */
			if (aimutil_get8(&conn->header[0]) != 0x2a)
			{
				flap_connection_schedule_destroy(conn,
						OSCAR_DISCONNECT_INVALID_DATA, NULL);
				break;
			}

			/* Initialize a new temporary FlapFrame for incoming data */
			conn->buffer_incoming.channel = aimutil_get8(&conn->header[1]);
			conn->buffer_incoming.seqnum = aimutil_get16(&conn->header[2]);
			conn->buffer_incoming.data.len = aimutil_get16(&conn->header[4]);
			conn->buffer_incoming.data.data = g_new(guint8, conn->buffer_incoming.data.len);
			conn->buffer_incoming.data.offset = 0;
		}

		buflen = conn->buffer_incoming.data.len - conn->buffer_incoming.data.offset;
		if (buflen)
		{
			buf = &conn->buffer_incoming.data.data[conn->buffer_incoming.data.offset];
			/* Read data into the temporary FlapFrame until it is complete */
			if (conn->gsc)
				read = purple_ssl_read(conn->gsc, buf, buflen);
			else
				read = recv(conn->fd, buf, buflen, 0);

			/* Check if the FLAP server closed the connection */
			if (read == 0)
			{
				flap_connection_schedule_destroy(conn,
						OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
				break;
			}

			if (read < 0)
			{
				if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
					/* No worries */
					break;

				/* Error! */
				flap_connection_schedule_destroy(conn,
						OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
				break;
			}

			conn->buffer_incoming.data.offset += read;
			if (conn->buffer_incoming.data.offset < conn->buffer_incoming.data.len)
				/* Waiting for more data to arrive */
				break;
		}

		/* We have a complete FLAP!  Handle it and continue reading */
		byte_stream_rewind(&conn->buffer_incoming.data);
		parse_flap(conn->od, conn, &conn->buffer_incoming);
		conn->lastactivity = time(NULL);

		g_free(conn->buffer_incoming.data.data);
		conn->buffer_incoming.data.data = NULL;

		conn->header_received = 0;
	}
}
Esempio n. 6
0
static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, guint8 *cookie)
{
	aim_rxcallback_t userfunc;
	aim_tlv_t *block1, *servdatatlv;
	aim_tlvlist_t *list2;
	struct aim_incomingim_ch2_args args;
	aim_bstream_t bbs, sdbs, *sdbsptr = NULL;
	guint8 *cookie2;
	int ret = 0;

	char clientip1[30] = {""};
	char clientip2[30] = {""};
	char verifiedip[30] = {""};

	memset(&args, 0, sizeof(args));

	/*
	 * There's another block of TLVs embedded in the type 5 here. 
	 */
	block1 = aim_gettlv(tlvlist, 0x0005, 1);
	aim_bstream_init(&bbs, block1->value, block1->length);

	/*
	 * First two bytes represent the status of the connection.
	 *
	 * 0 is a request, 1 is a deny (?), 2 is an accept
	 */ 
	args.status = aimbs_get16(&bbs);

	/*
	 * Next comes the cookie.  Should match the ICBM cookie.
	 */
	cookie2 = aimbs_getraw(&bbs, 8);
	if (memcmp(cookie, cookie2, 8) != 0) 
		imcb_error(sess->aux_data, "rend: warning cookies don't match!");
	memcpy(args.cookie, cookie2, 8);
	g_free(cookie2);

	/*
	 * The next 16bytes are a capability block so we can
	 * identify what type of rendezvous this is.
	 */
	args.reqclass = aim_getcap(sess, &bbs, 0x10);

	/* 
	 * What follows may be TLVs or nothing, depending on the
	 * purpose of the message.
	 *
	 * Ack packets for instance have nothing more to them.
	 */
	list2 = aim_readtlvchain(&bbs);

	/*
	 * IP address from the perspective of the client.
	 */
	if (aim_gettlv(list2, 0x0002, 1)) {
		aim_tlv_t *iptlv;

		iptlv = aim_gettlv(list2, 0x0002, 1);

		g_snprintf(clientip1, sizeof(clientip1), "%d.%d.%d.%d",
				aimutil_get8(iptlv->value+0),
				aimutil_get8(iptlv->value+1),
				aimutil_get8(iptlv->value+2),
				aimutil_get8(iptlv->value+3));
	}

	/*
	 * Secondary IP address from the perspective of the client.
	 */
	if (aim_gettlv(list2, 0x0003, 1)) {
		aim_tlv_t *iptlv;

		iptlv = aim_gettlv(list2, 0x0003, 1);

		g_snprintf(clientip2, sizeof(clientip2), "%d.%d.%d.%d",
				aimutil_get8(iptlv->value+0),
				aimutil_get8(iptlv->value+1),
				aimutil_get8(iptlv->value+2),
				aimutil_get8(iptlv->value+3));
	}

	/*
	 * Verified IP address (from the perspective of Oscar).
	 *
	 * This is added by the server.
	 */
	if (aim_gettlv(list2, 0x0004, 1)) {
		aim_tlv_t *iptlv;

		iptlv = aim_gettlv(list2, 0x0004, 1);

		g_snprintf(verifiedip, sizeof(verifiedip), "%d.%d.%d.%d",
				aimutil_get8(iptlv->value+0),
				aimutil_get8(iptlv->value+1),
				aimutil_get8(iptlv->value+2),
				aimutil_get8(iptlv->value+3));
	}

	/*
	 * Port number for something.
	 */
	if (aim_gettlv(list2, 0x0005, 1))
		args.port = aim_gettlv16(list2, 0x0005, 1);

	/*
	 * Error code.
	 */
	if (aim_gettlv(list2, 0x000b, 1))
		args.errorcode = aim_gettlv16(list2, 0x000b, 1);

	/*
	 * Invitation message / chat description.
	 */
	if (aim_gettlv(list2, 0x000c, 1))
		args.msg = aim_gettlv_str(list2, 0x000c, 1);

	/*
	 * Character set.
	 */
	if (aim_gettlv(list2, 0x000d, 1))
		args.encoding = aim_gettlv_str(list2, 0x000d, 1);
	
	/*
	 * Language.
	 */
	if (aim_gettlv(list2, 0x000e, 1))
		args.language = aim_gettlv_str(list2, 0x000e, 1);

	/* Unknown -- two bytes = 0x0001 */
	if (aim_gettlv(list2, 0x000a, 1))
		;

	/* Unknown -- no value */
	if (aim_gettlv(list2, 0x000f, 1))
		;

	if (strlen(clientip1))
		args.clientip = (char *)clientip1;
	if (strlen(clientip2))
		args.clientip2 = (char *)clientip2;
	if (strlen(verifiedip))
		args.verifiedip = (char *)verifiedip;

	/*
	 * This is must be present in PROPOSALs, but will probably not
	 * exist in CANCELs and ACCEPTs.
	 *
	 * Service Data blocks are module-specific in format.
	 */
	if ((servdatatlv = aim_gettlv(list2, 0x2711 /* 10001 */, 1))) {

		aim_bstream_init(&sdbs, servdatatlv->value, servdatatlv->length);
		sdbsptr = &sdbs;
	}

	if (args.reqclass & AIM_CAPS_ICQSERVERRELAY)
		incomingim_ch2_icqserverrelay(sess, mod, rx, snac, userinfo, &args, sdbsptr);
	else if (args.reqclass & AIM_CAPS_CHAT)
		incomingim_ch2_chat(sess, mod, rx, snac, userinfo, &args, sdbsptr);


	if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
		ret = userfunc(sess, rx, channel, userinfo, &args);


	if (args.destructor)
		((ch2_args_destructor_t)args.destructor)(sess, &args);

	g_free((char *)args.msg);
	g_free((char *)args.encoding);
	g_free((char *)args.language);

	aim_freetlvchain(&list2);

	return ret;
}