Beispiel #1
0
GSList *
msn_tlvlist_read(const char *bs, size_t bs_len)
{
	GSList *list = NULL;

	while (bs_len > 0) {
		guint8 type, length;
		msn_tlv_t *tlv;

		if (bs_len == 3 && *bs == 0) {
			/* Padding to multiple of 4 */
			break;
		} else if (bs_len == 2 && *bs == 0) {
			/* Padding to multiple of 4 */
			break;
		} else if (bs_len == 1) {
			if (*bs == 0) {
				/* Padding to multiple of 4 */
				break;
			} else {
				/* TLV is not small enough to fit here */
				msn_tlvlist_free(list);
				return NULL;
			}
		}

		type = msn_pop8(bs);
		length = msn_pop8(bs);
		bs_len -= 2;

		if (length > bs_len) {
			msn_tlvlist_free(list);
			return NULL;
		}

		tlv = createtlv(type, length, NULL);
		if (length > 0) {
			tlv->value = g_memdup(bs, length);
			if (!tlv->value) {
				freetlv(tlv);
				msn_tlvlist_free(list);
				return NULL;
			}
		}

		bs_len -= length;
		bs += length;

		list = g_slist_prepend(list, tlv);
	}

	return g_slist_reverse(list);
}
Beispiel #2
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;
}
Beispiel #3
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;
}
Beispiel #4
0
static GSList *
aim_tlv_read(GSList *list, ByteStream *bs)
{
	guint16 type, length;
	aim_tlv_t *tlv;

	type = byte_stream_get16(bs);
	length = byte_stream_get16(bs);

#if 0
	/*
	 * This code hasn't been needed in years.  It's been commented
	 * out since 2003, at the latest.  It seems likely that it was
	 * just a bug in their server code that has since been fixed.
	 * In any case, here's the orignal comment, kept for historical
	 * purposes:
	 *
	 * 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
	 * there's no special cases to this special case.
	 *   - mid (30jun2000)
	 */
	if ((type == 0x0013) && (length != 0x0002)) {
		length = 0x0002;
		return list;
	}
#endif
	if (length > byte_stream_empty(bs)) {
		aim_tlvlist_free(list);
		return NULL;
	}

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

	return g_slist_prepend(list, tlv);
}
Beispiel #5
0
/**
 * aim_freetlvchain - Free a TLV chain structure
 * @list: Chain to be freed
 *
 * Walks the list of TLVs in the passed TLV chain and
 * frees each one. Note that any references to this data
 * should be removed before calling this.
 *
 */
faim_internal void aim_freetlvchain(aim_tlvlist_t **list)
{
	aim_tlvlist_t *cur;

	if (!list || !*list)
		return;

	for (cur = *list; cur; ) {
		aim_tlvlist_t *tmp;
		
		freetlv(&cur->tlv);

		tmp = cur->next;
		free(cur);
		cur = tmp;
	}

	list = NULL;

	return;
}
Beispiel #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
 */
faim_internal aim_tlvlist_t *aim_tlvlist_read(aim_bstream_t *bs)
{
	aim_tlvlist_t *list = NULL, *cur;
	
	while (aim_bstream_empty(bs) > 0) {
		fu16_t type, length;

		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 {

			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;
				}
			}

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

	return list;
}