Ejemplo n.º 1
0
faim_internal int aimbs_putbs(aim_bstream_t *bs, aim_bstream_t *srcbs, int len)
{

    if (aim_bstream_empty(srcbs) < len)
        return 0; /* XXX throw exception (underrun) */

    if (aim_bstream_empty(bs) < len)
        return 0; /* XXX throw exception (overflow) */

    memcpy(bs->data + bs->offset, srcbs->data + srcbs->offset, len);
    bs->offset += len;
    srcbs->offset += len;

    return len;
}
Ejemplo n.º 2
0
/* called for both reply and change-reply */
static int infochange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
{

	/*
	 * struct {
	 *    guint16 perms;
	 *    guint16 tlvcount;
	 *    aim_tlv_t tlvs[tlvcount];
	 *  } admin_info[n];
	 */
	while (aim_bstream_empty(bs)) {
		guint16 perms, tlvcount;

		perms = aimbs_get16(bs);
		tlvcount = aimbs_get16(bs);

		while (tlvcount && aim_bstream_empty(bs)) {
			aim_rxcallback_t userfunc;
			guint16 type, len;
			guint8 *val;
			int str = 0;

			type = aimbs_get16(bs);
			len = aimbs_get16(bs);

			if ((type == 0x0011) || (type == 0x0004)) {
				str = 1;
			}

			if (str) {
				val = (guint8 *) aimbs_getstr(bs, len);
			} else {
				val = aimbs_getraw(bs, len);
			}

			/* XXX fix so its only called once for the entire packet */
			if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) {
				userfunc(sess, rx, (snac->subtype == 0x0005) ? 1 : 0, perms, type, len, val, str);
			}

			g_free(val);

			tlvcount--;
		}
	}

	return 1;
}
Ejemplo n.º 3
0
static int consumesnac(aim_session_t *sess, aim_frame_t *rx)
{
	aim_module_t *cur;
	aim_modsnac_t snac;

	if (aim_bstream_empty(&rx->data) < 10)
		return 0;

	snac.family = aimbs_get16(&rx->data);
	snac.subtype = aimbs_get16(&rx->data);
	snac.flags = aimbs_get16(&rx->data);
	snac.id = aimbs_get32(&rx->data);

	for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) {

		if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) && 
				(cur->family != snac.family))
			continue;

		if (cur->snachandler(sess, cur, rx, &snac, &rx->data))
			return 1;

	}

	return 0;
}
Ejemplo n.º 4
0
/*
 * This still takes a length parameter even with a bstream because capabilities
 * are not naturally bounded.
 * 
 */
faim_internal fu16_t aim_getcap(aim_session_t *sess, aim_bstream_t *bs, int len)
{
	fu16_t flags = 0;
	int offset;

	for (offset = 0; aim_bstream_empty(bs) && (offset < len); offset += 0x10) {
		fu8_t *cap;
		int i, identified;

		cap = aimbs_getraw(bs, 0x10);

		for (i = 0, identified = 0; !(aim_caps[i].flag & AIM_CAPS_LAST); i++) {

			if (memcmp(&aim_caps[i].data, cap, 0x10) == 0) {
				flags |= aim_caps[i].flag;
				identified++;
				break; /* should only match once... */

			}
		}

		if (!identified)
			faimdprintf(sess, 0, "unknown capability!\n");

		free(cap);
	}

	return flags;
}
Ejemplo n.º 5
0
static int negchan_middle(aim_session_t *sess, aim_frame_t *fr)
{
	aim_tlvlist_t *tlvlist;
	char *msg = NULL;
	fu16_t code = 0;
	aim_rxcallback_t userfunc;
	int ret = 1;

	if (aim_bstream_empty(&fr->data) == 0) {
		/* XXX should do something with this */
		return 1;
	}

	/* Used only by the older login protocol */
	/* XXX remove this special case? */
	if (fr->conn->type == AIM_CONN_TYPE_AUTH)
		return consumenonsnac(sess, fr, 0x0017, 0x0003);

	tlvlist = aim_tlvlist_read(&fr->data);

	if (aim_tlv_gettlv(tlvlist, 0x0009, 1))
		code = aim_tlv_get16(tlvlist, 0x0009, 1);

	if (aim_tlv_gettlv(tlvlist, 0x000b, 1))
		msg = aim_tlv_getstr(tlvlist, 0x000b, 1);

	if ((userfunc = aim_callhandler(sess, fr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
		ret = userfunc(sess, fr, code, msg);

	aim_tlvlist_free(&tlvlist);

	free(msg);

	return ret;
}
Ejemplo n.º 6
0
/**
 * Read a TLV chain from a buffer.
 *
 * Reads and parses a series of TLV patterns from a data buffer; the
 * returned structure is manipulatable with the rest of the TLV
 * routines.  When done with a TLV chain, aim_tlvlist_free() should
 * be called to free the dynamic substructures.
 *
 * XXX There should be a flag setable here to have the tlvlist contain
 * bstream references, so that at least the ->value portion of each 
 * element doesn't need to be malloc/memcpy'd.  This could prove to be
 * just as effecient as the in-place TLV parsing used in a couple places
 * in libfaim.
 *
 * @param bs Input bstream
 * @param num The max number of TLVs that will be read, or -1 if unlimited.  
 *        There are a number of places where you want to read in a tlvchain, 
 *        but the chain is not at the end of the SNAC, and the chain is 
 *        preceeded by the number of TLVs.  So you can limit that with this.
 */
faim_internal aim_tlvlist_t *aim_tlvlist_readnum(aim_bstream_t *bs, fu16_t num)
{
	aim_tlvlist_t *list = NULL, *cur;

	while ((aim_bstream_empty(bs) > 0) && (num != 0)) {
		fu16_t type, length;

		type = aimbs_get16(bs);
		length = aimbs_get16(bs);

		if (length > aim_bstream_empty(bs)) {
			aim_tlvlist_free(&list);
			return NULL;
		}

		cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
		if (!cur) {
			aim_tlvlist_free(&list);
			return NULL;
		}

		memset(cur, 0, sizeof(aim_tlvlist_t));

		cur->tlv = createtlv(type, length, NULL);
		if (!cur->tlv) {
			free(cur);
			aim_tlvlist_free(&list);
			return NULL;
		}
		if (cur->tlv->length > 0) {
			cur->tlv->value = aimbs_getraw(bs, length);
			if (!cur->tlv->value) {
				freetlv(&cur->tlv);
				free(cur);
				aim_tlvlist_free(&list);
				return NULL;
			}
		}

		if (num > 0)
			num--;
		cur->next = list;
		list = cur;
	}

	return list;
}
Ejemplo n.º 7
0
/**
 * aim_readtlvchain_len - Read a TLV chain from a buffer.
 * @param bs Input bstream
 * @param len The max length in bytes that will be read.
 *        There are a number of places where you want to read in a tlvchain, 
 *        but the chain is not at the end of the SNAC, and the chain is 
 *        preceeded by the length of the TLVs.  So you can limit that with this.
 *
 * Reads and parses a series of TLV patterns from a data buffer; the
 * returned structure is manipulatable with the rest of the TLV
 * routines.  When done with a TLV chain, aim_freetlvchain() should
 * be called to free the dynamic substructures.
 *
 * XXX There should be a flag setable here to have the tlvlist contain
 * bstream references, so that at least the ->value portion of each 
 * element doesn't need to be malloc/memcpy'd.  This could prove to be
 * just as effecient as the in-place TLV parsing used in a couple places
 * in libfaim.
 *
 */
faim_internal aim_tlvlist_t *aim_readtlvchain_len(aim_bstream_t *bs, fu16_t len)
{
	aim_tlvlist_t *list = NULL, *cur;

	while ((aim_bstream_empty(bs) > 0) && (len > 0)) {
		fu16_t type, length;

		type = aimbs_get16(bs);
		length = aimbs_get16(bs);

		if (length > aim_bstream_empty(bs)) {
			aim_freetlvchain(&list);
			return NULL;
		}

		cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
		if (!cur) {
			aim_freetlvchain(&list);
			return NULL;
		}

		memset(cur, 0, sizeof(aim_tlvlist_t));

		cur->tlv = createtlv();
		if (!cur->tlv) {
			free(cur);
			aim_freetlvchain(&list);
			return NULL;
		}
		cur->tlv->type = type;
		if ((cur->tlv->length = length)) {
		       cur->tlv->value = aimbs_getraw(bs, length);
		       if (!cur->tlv->value) {
			       freetlv(&cur->tlv);
			       free(cur);
			       aim_freetlvchain(&list);
			       return NULL;
		       }
		}

		len -= aim_sizetlvchain(&cur);
		cur->next = list;
		list = cur;
	}

	return list;
}
Ejemplo n.º 8
0
faim_internal fu16_t aimbs_getle16(aim_bstream_t *bs)
{

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

    bs->offset += 2;

    return aimutil_getle16(bs->data + bs->offset - 2);
}
Ejemplo n.º 9
0
faim_internal fu32_t aimbs_getle32(aim_bstream_t *bs)
{

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

    bs->offset += 4;

    return aimutil_getle32(bs->data + bs->offset - 4);
}
Ejemplo n.º 10
0
int aimbs_putle8(aim_bstream_t *bs, guint8 v)
{

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

	bs->offset += aimutil_putle8(bs->data + bs->offset, v);

	return 1;
}
Ejemplo n.º 11
0
faim_internal int aimbs_putle16(aim_bstream_t *bs, fu16_t v)
{

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

    bs->offset += aimutil_putle16(bs->data + bs->offset, v);

    return 2;
}
Ejemplo n.º 12
0
int aimbs_put16(aim_bstream_t *bs, guint16 v)
{

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

	bs->offset += aimutil_put16(bs->data + bs->offset, v);

	return 2;
}
Ejemplo n.º 13
0
faim_internal int aimbs_putle32(aim_bstream_t *bs, fu32_t v)
{

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

    bs->offset += aimutil_putle32(bs->data + bs->offset, v);

    return 1;
}
Ejemplo n.º 14
0
faim_internal fu8_t aimbs_getle8(aim_bstream_t *bs)
{

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

    bs->offset++;

    return aimutil_getle8(bs->data + bs->offset - 1);
}
Ejemplo n.º 15
0
faim_internal int aim_bstream_advance(aim_bstream_t *bs, int n)
{

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

    bs->offset += n;

    return n;
}
Ejemplo n.º 16
0
guint16 aimbs_getle16(aim_bstream_t *bs)
{

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

	}
	bs->offset += 2;

	return aimutil_getle16(bs->data + bs->offset - 2);
}
Ejemplo n.º 17
0
guint32 aimbs_getle32(aim_bstream_t *bs)
{

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

	}
	bs->offset += 4;

	return aimutil_getle32(bs->data + bs->offset - 4);
}
Ejemplo n.º 18
0
int aimbs_putle32(aim_bstream_t *bs, guint32 v)
{

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

	}
	bs->offset += aimutil_putle32(bs->data + bs->offset, v);

	return 1;
}
Ejemplo n.º 19
0
faim_internal int aimbs_putraw(aim_bstream_t *bs, const fu8_t *v, int len)
{

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

    memcpy(bs->data + bs->offset, v, len);
    bs->offset += len;

    return len;
}
Ejemplo n.º 20
0
guint8 aimbs_getle8(aim_bstream_t *bs)
{

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

	}
	bs->offset++;

	return aimutil_getle8(bs->data + bs->offset - 1);
}
Ejemplo n.º 21
0
faim_internal int aimbs_getrawbuf(aim_bstream_t *bs, fu8_t *buf, int len)
{

    if (aim_bstream_empty(bs) < len)
        return 0;

    memcpy(buf, bs->data + bs->offset, len);
    bs->offset += len;

    return len;
}
Ejemplo n.º 22
0
int aimbs_putraw(aim_bstream_t *bs, const guint8 *v, int len)
{

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

	}
	memcpy(bs->data + bs->offset, v, len);
	bs->offset += len;

	return len;
}
Ejemplo n.º 23
0
int aimbs_getrawbuf(aim_bstream_t *bs, guint8 *buf, int len)
{

	if (aim_bstream_empty(bs) < len) {
		return 0;
	}

	memcpy(buf, bs->data + bs->offset, len);
	bs->offset += len;

	return len;
}
Ejemplo n.º 24
0
static int consumesnac(aim_session_t *sess, aim_frame_t *rx)
{
	aim_module_t *cur;
	aim_modsnac_t snac;

	if (aim_bstream_empty(&rx->data) < 10)
		return 0;

	snac.family = aimbs_get16(&rx->data);
	snac.subtype = aimbs_get16(&rx->data);
	snac.flags = aimbs_get16(&rx->data);
	snac.id = aimbs_get32(&rx->data);

	/* SNAC flags are apparently uniform across all SNACs, so we handle them here */
	if (snac.flags & 0x0001) {
		/*
		 * This means the SNAC will be followed by another SNAC with 
		 * related information.  We don't need to do anything about 
		 * this here.
		 */
	}
	if (snac.flags & 0x8000) {
		/*
		 * This packet contains the version of the family that this SNAC is 
		 * in.  You get this when your SSI module is version 2 or higher.  
		 * For now we have no need for this, but you could always save 
		 * it as a part of aim_modnsac_t, or something.  The format is...
		 * 2 byte length of total mini-header (which is 6 bytes), then TLV 
		 * of  type 0x0001, length 0x0002, value is the 2 byte version 
		 * number
		 */
		aim_bstream_advance(&rx->data, aimbs_get16(&rx->data));
	}

	for (cur = (aim_module_t *)sess->modlistv; cur; cur = cur->next) {

		if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) &&
				(cur->family != snac.family))
			continue;

		if (cur->snachandler(sess, cur, rx, &snac, &rx->data))
			return 1;

	}

	return 0;
}
Ejemplo n.º 25
0
faim_internal int aim_parse_unknown(aim_session_t *sess, aim_frame_t *frame, ...)
{
	int i;

	faimdprintf(sess, 1, "\nRecieved unknown packet:");

	for (i = 0; aim_bstream_empty(&frame->data); i++) {
		if ((i % 8) == 0)
			faimdprintf(sess, 1, "\n\t");

		faimdprintf(sess, 1, "0x%2x ", aimbs_get8(&frame->data));
	}

	faimdprintf(sess, 1, "\n\n");

	return 1;
}
Ejemplo n.º 26
0
faim_internal int aim_putcap(aim_bstream_t *bs, fu32_t caps)
{
	int i;

	if (!bs)
		return -EINVAL;

	for (i = 0; aim_bstream_empty(bs); i++) {

		if (aim_caps[i].flag == AIM_CAPS_LAST)
			break;

		if (caps & aim_caps[i].flag)
			aimbs_putraw(bs, aim_caps[i].data, 0x10);

	}

	return 0;
}
Ejemplo n.º 27
0
static int userlistchange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
{
	aim_userinfo_t *userinfo = NULL;
	aim_rxcallback_t userfunc;
	int curcount = 0, ret = 0;

	while (aim_bstream_empty(bs)) {
		curcount++;
		userinfo = realloc(userinfo, curcount * sizeof(aim_userinfo_t));
		aim_extractuserinfo(sess, bs, &userinfo[curcount-1]);
	}

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

	free(userinfo);

	return ret;
}
Ejemplo n.º 28
0
/**
 * aim_readtlvchain - Read a TLV chain from a buffer.
 * @buf: Input buffer
 * @maxlen: Length of input buffer
 *
 * Reads and parses a series of TLV patterns from a data buffer; the
 * returned structure is manipulatable with the rest of the TLV
 * routines.  When done with a TLV chain, aim_freetlvchain() should
 * be called to free the dynamic substructures.
 *
 * XXX There should be a flag setable here to have the tlvlist contain
 * bstream references, so that at least the ->value portion of each 
 * element doesn't need to be malloc/memcpy'd.  This could prove to be
 * just as effecient as the in-place TLV parsing used in a couple places
 * in libfaim.
 *
 */
faim_internal aim_tlvlist_t *aim_readtlvchain(aim_bstream_t *bs)
{
	aim_tlvlist_t *list = NULL, *cur;
	fu16_t type, length;

	while (aim_bstream_empty(bs)) {

		type = aimbs_get16(bs);
		length = aimbs_get16(bs);

#if 0 /* temporarily disabled until I know if they're still doing it or not */
		/*
		 * Okay, so now AOL has decided that any TLV of
		 * type 0x0013 can only be two bytes, despite
		 * what the actual given length is.  So here 
		 * we dump any invalid TLVs of that sort.  Hopefully
		 * theres no special cases to this special case.
		 *   - mid (30jun2000)
		 */
		if ((type == 0x0013) && (length != 0x0002))
			length = 0x0002;
#else
		if (0)
			;
#endif
		else {

			cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
			memset(cur, 0, sizeof(aim_tlvlist_t));

			cur->tlv = createtlv();	
			cur->tlv->type = type;
			if ((cur->tlv->length = length))
			       cur->tlv->value = aimbs_getraw(bs, length);	

			cur->next = list;
			list = cur;
		}
	}

	return list;
}
Ejemplo n.º 29
0
static int missedcall(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
{
	int ret = 0;
	aim_rxcallback_t userfunc;
	guint16 channel, nummissed, reason;
	aim_userinfo_t userinfo;

	while (aim_bstream_empty(bs)) {	

		channel = aimbs_get16(bs);
		aim_extractuserinfo(sess, bs, &userinfo);
		nummissed = aimbs_get16(bs);
		reason = aimbs_get16(bs);

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

	return ret;
}
Ejemplo n.º 30
0
/*
 * Should be generic enough to handle the errors for all groups.
 *
 */
static int generror(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs)
{
    int ret = 0;
    int error = 0;
    aim_rxcallback_t userfunc;
    aim_snac_t *snac2;

    snac2 = aim_remsnac(sess, snac->id);

    if (aim_bstream_empty(bs))
        error = aimbs_get16(bs);

    if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
        ret = userfunc(sess, rx, error, snac2 ? snac2->data : NULL);

    if (snac2)
        g_free(snac2->data);
    g_free(snac2);

    return ret;
}